soapui loadtest 参数只能有http请求组成吗

[图书连载]负载测试(Load Test)
发表于 10:33|
作者陈秋歌
摘要:本文为电子工业出版社推出的《构筑敏捷的开发团队:微软Visual Studio 2010实战兵法》图书第八章连载之二十三。 负载测试(Load Testing)是确定在各种工作负载下系统的性能,目标是测试当负载
本文为电子工业出版社推出的《构筑敏捷的开发团队:微软Visual Studio 2010实战兵法》图书第八章连载之二十三。
负载测试(Load Testing)是确定在各种工作负载下系统的性能,目标是测试当负载逐渐增加时,系统组成部分的相应输出项,例如通过量、响应时间、CPU负载、内存使用等来决定系统的性能。负载测试是一个分析软件应用程序和支撑架构、模拟真实环境的使用,从而确定能够接收的性能过程。压力测试(Stress Testing)是通过确定一个系统的瓶颈或者不能接收的性能点,来获得系统能提供的最大服务级别的测试。
Visual Studio Team System 2010给我们提供了一个创建并运行Load tests的工具。Load Test的基本目标就是模拟许多用户同时访问服务器。当从一个Load tests里面添加Web tests/Unit tests后,会模拟多个用户同时连接到服务器上,并向服务器发送多个HTTP请求。可以设置Load tests的属性,并广泛地运用到你的Web tests中。
应用&实践:使用Visual Studio 2010创建一个负载测试(Load Test)
1.创建一个负载测试
Visual Studio 2010负载试验提供了每个负载测试的场景设置,使您可在整个负载范围内进行场景测试的控制,因此,新的选项允许更容易地创建一个负载测试,精确模型的负载可以在服务器下执行模拟测试。
(1)设置负载测试的名称和思考时间的配置
首先,使用负载测试向导创(Load Test Wizard)建一个新的负载测试。打开资源解决方案浏览器(Solution Explorer),右键菜单中选&Add&,单击&Load Test..&,在弹出安装向导中,单击&Next&键,弹出场景向导界面。场景为配置个性化测试提供了灵活性,它可以模拟复杂真实的工作负载。输入场景名字为&TestScenario&,选择&user normal distribution centered on recorded think times(正态分布用户为中心的思考时间记录)&,设置思考时间为2秒(思考时间根据实际需要而设置),然后单击&Next&,如图1所示。
图1& 指定负载模式
在完成向导后,也可以返回并编辑负载测试,并更改的设置,在向导中选择适用的配置选项。
负载测试包含一个或多个场景,这是用来模拟如何与一组用户的服务器应用程序进行交互。一个人的情况涉及负载模式,测试组合,浏览器结构,网络结构。这些设置的每一个对应于网页中的负载测试向导。
(2)测试组合类
Load pattern属性指定了在一个load test过程中如何调整模拟的用户数。选择Constant Load,设置用户数为25,然后单击&Next&,如图2所示。
图2& 选择组合模式
在该模式中包括基于总测试数、基于虚拟用户数、基于用户节奏,不同的建模方式其分配的百分比不同。负载模式可以指定新用户的增加活跃的虚拟用户的数量。再负载测试多个负载模式的能力,来实现测试目标。我们必须指定负载测试中每个场景的负载模式。
(3)测试组合
将所有的webtest组合在一起,(Test mix model)模拟最真实用户操作系统的环境。我们可以有多个工作流,这样就更加贴近终端用户交互你应用程序的情况。
①选择&Based on the total number of tests&,然后单击&Next&,如图3所示。
图3& 测试组合模式(基于测试总数)
其中各组合模式的介绍参考图3中的选中部分,该说明有对不同的模型进行介绍。
②如果选择&Based on sequential test order&,然后选择&Next&,向导页面将添加到顺序的测试。此项是新的&Test Mix&基于顺序测试项(如图4(1)所示),每个虚拟用户将通过顺序测试和语序对其设置,此选项可在新的负载测试和新的场景中使用。如图4(2)所示。
图4(1)& 测试组合模式(基于顺序测试顺序)
图4(2)& 基于顺序测试场景
如图2所示,图表文字说明的行为,并显示与25个虚拟用户和两个场景的测试例子。无需输入百分比或为其他测试混合类型协调信息。如果创建了这个测试组合类型的负载测试方案,可以随后使用负载测试编辑器的混合编辑器更改测试混合型,或添加、删除或更改测试顺序向导。
(4)添加组合
Test mix指定了虚拟用户在一个load test场景中运行一个给定测试的可能性。能让你更加真实地模拟负载。我们单击&Add&添加一个Web test 或 unit test(在这里我们可以增加一个Webtest测试),选择一个测试项,然后单击&OK&。如图5所示。
图5& 添加测试组合并进行方案分配
在图5中,可以对组合的测试项目进行百分比分配,当对其中某个测试项目加锁后,更改其他项目的百分比,该测试项目的百分比不能再进行更改,但是可以对锁定的测试进行独立修改。
提示:Web性能测试(Web Performance Test)
VS 2010版本中,微软把Web Test改为Web Performance Test,可以在VS 2010解决方案资源管理器,打开一个测试项目,右键菜单|Add|Web Performance Test或者在VS 2010 IDE菜单Test|New Tes|Web Performance Test进行创建。创建时IE会自动弹出,当输入被测试Webz地址时,会自动录制脚本并可以手动生成C#或者VB脚本代码。然后加入到Load Test中进行集成测试中一部分,与Load Test 测试方式相似,在这里不再赘述。
&Web 测试&也称为声明性 Web 测试,它由一系列 HTTP 请求组成。Web 测试通过发出 HTTP 请求在协议层工作。Web 测试不运行 JavaScript。但是,可以在运行时通过使用 Web 测试插件、Web 测试请求插件、提取规则或编码的 Web 测试来模拟 JavaScript 操作。 它用于测试 Web 应用程序的功能以及在负载下测试 Web 应用程序。Web 测试可用于性能测试和压力测试。 通过在浏览器会话中记录活动,可以创建 Web 测试。还可以使用 Web 测试编辑器手动构建 Web 测试。 要测试 Web 应用程序,请通过记录在 Web 应用程序中导航的测试来创建 Web 测试。
(5)添加网络组合
模拟在不同的网络环境下访问系统。Network mix指定了虚拟用户运行一个网络profile的可能性。选择网络类型&LAN&,然后单击&Next&按钮,如图6所示。
图6& 添加网络组合
可以添加多个网络组合,并可以对其网络类型进行百分比分配。当锁定其中某个网络类型的百分比后,修改其他的网络类型,该网络类型的百分比不发生变化,但是可以独立修改该网络类型的百分比。
(6)浏览器组合
模拟不同的浏览器访问Web系统。Browser mix指定了虚拟用户运行多种浏览器综合测试的可能性。选择网络类型&Internet Explorer 8.0&,然后单击&Next&按钮,如图7所示。
图7& 添加浏览器组合
可以添加多个浏览器的组合。也可以对其浏览器进行百分比分配,当锁定其中某个浏览器的百分比后,修改其他的浏览器,该浏览器的百分比不发生变化,但是可以独立修改该浏览器的百分比。
(7)计数器设置(Counter sets)
添加被监控的服务器的计算机名字或者IP地址,以监控其具体的计数器。Counter sets是一系列系统性能计数器,在运行一个load test过程中对性能监视很有用,添加计算机名&Local Computer&,选择&Next&,如图8所示。
图8& 添加计数设置
添加计算机。输入需要被监控计算机的名字或IP地址,并选择需要监控的参数。选中参数后,该参数会在右侧显示。
(8)运行设置
模拟虚拟用户在系统中运行的时间和采样速率等。The run settings确定了测试的时间长度、warm-up期限、采样率、连接模型 (仅用于Web tests)、结果存储的类型、有效等级和SQL跟踪。我们选择测试时间长度为5分钟,然后单击 &Finish&按钮,创建了一个名为&LoadTest1&的负载测试。如图9所示。查看测试结果,如图10所示。
图9& 运行设置
图10& 查看结果显示
推荐阅读相关主题:
网友评论有(0)
CSDN官方微信
扫描二维码,向CSDN吐槽
微信号:CSDNnews
相关热门文章Bottle对HTTP请求的处理
Bottle对HTTP请求的处理
最近玩这个框架, 分析了一下它的源码, 顺便也理一下它是怎么处理HTTP请求的.
我们先分析下bottle.py的代码结构. 这个单文件的框架有2900多行, 大致结构如下(手头的版本是0.10.7):
: 模块载入, 兼容性调整
: 逻辑无关的工具函数和工具类定义
: 异常定义. 需要注意的是, 不需要消息体的HTTP响应, 例如HTTP重定向之类, 在bottle中也被处理成一种异常.
: URL映射相关逻辑, 包括若干个路由异常的定义.
: 主Bottle类的定义.
: 装HTTP请求和响应的类的定义. 微型框架啥都可以省省, 但是这个如果再省, 就不能被称为是框架了.
: 各种插件.
: 各种数据结构.
: 乱七八糟的小函数.
: 框架虽小, 兼容的服务器倒真不少...
: 应用控制, 也挺乱的, 两个用来载入app, 一个起server, 还有一个用来自动重启server(这个都有啊喂, 你真是微型框架咩).
: 模板渲染及处理, 兼容的模板系统也不少.
2830-EOF : 变量定义及一些实例化, 以及起内置服务器的main函数.
由于有实例化的部分, 我们得先看看这段. 一旦你要从bottle.py中引入一个名字到你自己的模块, 这些代码就得执行一遍. 除了那些对变量的定义外, 这一段做了下面几件事情:
def make_default_app_wrapper(name):
''' Return a callable that relays calls to the current default app. '''
@functools.wraps(getattr(Bottle, name))
def wrapper(*a, **ka):
return getattr(app(), name)(*a, **ka)
return wrapper
for name in '''route get post put delete error mount
hook install uninstall'''.split():
globals()[name] = make_default_app_wrapper(name)
url = make_default_app_wrapper('get_url')
#: A thread-safe instance of :class:`Request` representing the `current` request.
request = Request()
#: A thread-safe instance of :class:`Response` used to build the HTTP response.
response = Response()
#: A thread-safe namespace. Not used by Bottle.
local = threading.local()
# Initialize app stack (create first empty Bottle app)
# BC: 0.6.4 and needed for run()
app = default_app = AppStack()
app.push()
前面这段修改globals()是用make_default_app_wrapper这个函数将Bottle中的这些装饰器放到全局命名空间里来. 例如, 你原本需要写@app.get, 现在写成@get就行了. 后面这段注释已经说得很明白了, 我就不再多说.
线程初始化
为了分析HTTP请求的处理. 我们从wsgi脚本开始看. 我本地一个wsgi脚本的内容如下:
#coding=utf-8
import sys
sys.path.append('/home/apache/suisuinian')
from suisuinian.views import app as application
这一段一定程度上模仿了Django的将项目目录加入sys.path的做法. Bottle官方文档里面的做法是将当前工作路径切到wsgi脚本所在的文件夹, 这一点, 虽然我完全能够理解其目的, 我个人不太欣赏.
我们就从这儿开始我们的旅程, apache重启后, wsgi线程还没有启动. 这时, 我们向服务器发起一个HTTP请求, 则会执行这个wsgi脚本. 这个脚本做的事情不外设置路径和从视图函数中导入application这个对象. 视图函数是这么写的:
from bottle import app
app = app()
@app.get('/test')
def test():
# display a test string.
return 'test'
这一段代码从bottle.py中拿出AppStack, 并从中拿出初始化过的Bottle实例, 再重命名为app, 我们首先看看AppStack的具体逻辑:
class AppStack(list):
&&& A stack-like list. Calling it returns the head of the stack. &&&
def __call__(self):
&&& Return the current default application. &&&
return self[-1]
def push(self, value=None):
&&& Add a new :class:`Bottle` instance to the stack &&&
if not isinstance(value, Bottle):
value = Bottle()
self.append(value)
return value
前面说了, 在从bottle.py导出模块时就会执行一段代码, 包括AppStack的实例化和对其进行push操作. AppStack的实例化就是对一个列表的实例化, 参数为空, 所以此时列表也为空. 进行push操作时, 如果参数和我们现在一样为空, 则会实例化一个新的Bottle对象. 最后, 我们将这个对象(或者命令行下给出的另一个Bottle实例)放到栈顶. 如我们前面的代码所示, 我们会在视图中调用AppStack的__call__方法, 拿到这个默认的Bottle实例.
Bottle的实例化
接下来, 我们看看Bottle的实例化过程具体做了什么:
class Bottle(object):
&&& WSGI application &&&
def __init__(self, catchall=True, autojson=True, config=None):
self.routes = [] # List of installed :class:`Route` instances.
self.router = Router() # Maps requests to :class:`Route` instances.
self.plugins = [] # List of installed plugins.
self.error_handler = {}
#: If true, most exceptions are catched and returned as :exc:`HTTPError`
self.config = ConfigDict(config or {})
self.catchall = catchall
#: An instance of :class:`HooksPlugin`. Empty by default.
self.hooks = HooksPlugin()
self.install(self.hooks)
if autojson:
self.install(JSONPlugin())
self.install(TemplatePlugin())
先从整体看看这个初始化的过程. 整个过程中定义了若干个容器来放app的属性, 包括插件, URL映射表等等. Bottle的实例化过程中实例化了一个Router对象. Router的核心实例化代码为:
class Router(object):
def __init__(self):
self.rules
= {} # A {rule: Rule} mapping
self.builder
= {} # A rule/name-&build_info mapping
self.static
= {} # Cache for static routes: {path: {method: target}}
self.dynamic
= [] # Cache for dynamic routes. See _compile()
self.filters = {'re': self.re_filter, 'int': self.int_filter,
'float': self.float_filter, 'path': self.path_filter}
可以看出, Router就是URL映射器了.
另外, Bottle初始化过程中还实例化了一个ConfigDict对象. 这个对象是在dict对象上加了一些扩展, 能够用类似类属性的方式来访问字典的值. 具体来说还是一个装配置的容器. 另外, Bottle的实例化完成后, 装载了三个插件(Hooks, JSON和模板).
路由表的载入
为了避免思绪混乱, 我们在继续之前, 先看看目前做了哪些事情:
1. Apache找到我们的wsgi脚本.
2. wsgi脚本开始从我们的视图函数中载入app这个对象.
3. 我们的视图函数开始载入bottle.py中的对象.
4. bottle.py完成初始化.
好吧, 到现在, 我们已经完成bottle.py的初始化了, 我们的视图函数可以正常地载入app这个对象了. 接下来, 它兴致盎然地完成了app = app()这一步. 我们之前看过AppStack的代码, 知道这一步会用一个Bottle对象替换一个AppStack对象. 用这种名字替换是会让人引起混乱的, 这一方面是我的错, 另一方面, 代码中这一点也够混乱. 为了让你看得更清楚一点, 我将视图函数的内容改写在下面:
from bottle import app as appstack_obj
app = appstack_obj()
@app.get('/test')
def test():
# display a test string.
return &test&
到这儿, 我们已经处理完了app相关的逻辑, 但是在我们的wsgi脚本完成对app这个对象的载入前, python还会处理后面函数的初始化(虽然没有执行). 在这个过程中, url映射关系被放进了Bottle对象中. 具体我们来看app.get方法. 这个方法要和app.route一起看:
def get(self, path=None, method='GET', **options):
&&& Equals :meth:`route`. &&&
return self.route(path, method, **options)
def route(self, path=None, method='GET', callback=None, name=None,
apply=None, skip=None, **config):
if callable(path): path, callback = None, path
plugins = makelist(apply)
skiplist = makelist(skip)
def decorator(callback):
# TODO: Documentation and tests
if isinstance(callback, basestring): callback = load(callback)
for rule in makelist(path) or yieldroutes(callback):
for verb in makelist(method):
verb = verb.upper()
route = Route(self, rule, verb, callback, name=name,
plugins=plugins, skiplist=skiplist, **config)
self.routes.append(route)
self.router.add(rule, verb, route, name=name)
if DEBUG: route.prepare()
return callback
return decorator(callback) if callback else decorator
按照我们的视图函数, 传递给route这个方法的参数中path是'/test', method是'GET', callback是None. 到decorator时, callback是被装饰器包裹的函数, test. 后面基本是顺理成章的了: 实例化一个Route对象, 并将其加入app的路由表.
到这儿, 我们终于走到了wsgi脚本的结尾. 线程初始化完毕, 可以开始接受请求了.
HTTP请求的处理
HTTP请求是通过Bottle对象的__call__方法完成的:
def __call__(self, environ, start_response):
''' Each instance of :class:'Bottle' is a WSGI application. '''
return self.wsgi(environ, start_response)
实际上是调用了self.wsgi方法, 去掉异常处理后, 其核心代码如下:
def wsgi(self, environ, start_response):
&&& The bottle WSGI-interface. &&&
environ['bottle.app'] = self
request.bind(environ)
response.bind()
out = self._cast(self._handle(environ), request, response)
# rfc2616 section 4.3
if response._status_code in (100, 101, 204, 304)\
or request.method == 'HEAD':
if hasattr(out, 'close'): out.close()
start_response(response._status_line, list(response.iter_headers()))
return out
request这个变量是我们之前说过的, bottle.py文件结尾处实例化的LocalRequest对象. 具体的bind方法实际上执行了BaseRequest这个类的初始化方法:
class BaseRequest(DictMixin):
&&& A wrapper for WSGI environment dictionaries that adds a lot of
convenient access methods and properties. Most of them are read-only.&&&
#: Maximum size of memory buffer for :attr:`body` in bytes.
MEMFILE_MAX = 102400
#: Maximum number pr GET or POST parameters per request
MAX_PARAMS
def __init__(self, environ):
&&& Wrap a WSGI environ dictionary. &&&
#: The wrapped WSGI environ dictionary. This is the only real attribute.
#: All other attributes actually are read-only properties.
self.environ = environ
environ['bottle.request'] = self
好似除了将初始化参数提供给一个类变量, 并添加了一个属性外, 没做啥事情. 字典中的值都是按需读取的. DictMixin提供一个字典的骨架, 具体可以参考python官方文档. 顺口说一句, 这儿的MAX_PARAMS设置能够避免前几天热议的hash碰撞攻击.
response.bind()的作用也就是实例化一个BaseResponse对象, 这儿还没什么值, 讨论从略.
我们先看看要给_cast方法传递参数的_handle方法:
def _handle(self, environ):
route, args = self.router.match(environ)
environ['route.handle'] = environ['bottle.route'] = route
environ['route.url_args'] = args
return route.call(**args)
except HTTPResponse, r:
except RouteReset:
route.reset()
return self._handle(environ)
except (KeyboardInterrupt, SystemExit, MemoryError):
except Exception, e:
if not self.catchall: raise
stacktrace = format_exc(10)
environ['wsgi.errors'].write(stacktrace)
return HTTPError(500, &Internal Server Error&, e, stacktrace)
这一段里用Router实例做了url匹配, 于是再跟过去看看:
def match(self, environ):
''' Return a (target, url_agrs) tuple or raise HTTPError(400/404/405). '''
path, targets, urlargs = environ['PATH_INFO'] or '/', None, {}
if path in self.static:
targets = self.static[path]
for combined, rules in self.dynamic:
match = combined.match(path)
if not match: continue
getargs, targets = rules[match.lastindex - 1]
urlargs = getargs(path) if getargs else {}
if not targets:
raise HTTPError(404, &Not found: & + repr(environ['PATH_INFO']))
method = environ['REQUEST_METHOD'].upper()
if method in targets:
return targets[method], urlargs
if method == 'HEAD' and 'GET' in targets:
return targets['GET'], urlargs
if 'ANY' in targets:
return targets['ANY'], urlargs
allowed = [verb for verb in targets if verb != 'ANY']
if 'GET' in allowed and 'HEAD' not in allowed:
allowed.append('HEAD')
raise HTTPError(405, &Method not allowed.&,
header=[('Allow',&,&.join(allowed))])
这一段虽然比较长, 逻辑也比较复杂, 但是在官方文档的1.2.4节路由顺序(Routing Order)中已经有讲解, 此文从略. 匹配到适当的处理函数后, _handle函数中调用了对应的函数并返回.
对_cast方法有兴趣的同学可以自行围观代码, 但是这个方法基本是在查漏补缺了. 从_cast方法中出来后, 我们就调用start_response并返回内容了. 至此, bottle已完成了对一个最简单的HTTP请求的处理.温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
* XMLHttpRequest Object Pool&&*&&* @author legend &&&&* @link http:///?p=85&&* @Copyright &&*/&&&var XMLHttp = {&&_objPool: [],&&_getInstance: function ()&&{&&for (var i = 0; i & this._objPool. i ++)&&{&&if (this._objPool[i].readyState == 0 || this._objPool[i].readyState == 4)&&{&&return this._objPool[i];&&}&&}&&// IE5中不支持push方法&&this._objPool[this._objPool.length] = this._createObj();&&return this._objPool[this._objPool.length - 1];&&},&&_createObj: function ()&&{&&if (window.XMLHttpRequest)&&{&&var objXMLHttp = new XMLHttpRequest();&&}&&else&&{&&var MSXML = ['MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP'];&&for(var n = 0; n & MSXML. n ++)&&{&&try&&{&&var objXMLHttp = new ActiveXObject(MSXML[n]);&&break;&&}&&catch(e)&&{&&}&&}&&}&&&// mozilla某些版本没有readyState属性&&if (objXMLHttp.readyState == null)&&{&&objXMLHttp.readyState = 0;&&objXMLHttp.addEventListener("load", function ()&&{&&objXMLHttp.readyState = 4;&&if (typeof objXMLHttp.onreadystatechange == "function")&&{&&objXMLHttp.onreadystatechange();&&}&&}, false);&&}&&return objXMLH&&},&&// 发送请求(方法[post,get], 地址, 数据, 回调函数)&&sendReq: function (method, url, data, callback)&&{&&var objXMLHttp = this._getInstance();&&with(objXMLHttp)&&{&&try&&{&&// 加随机数防止缓存&&if (url.indexOf("?") & 0)&&{&&url += "&randnum=" + Math.random();&&}&&else&&{&&url += "?randnum=" + Math.random();&&}&&open(method, url, true);&&// 设定请求编码方式&&setRequestHeader('Content-Type', 'application/x-www-form- charset=UTF-8');&&send(data);&&onreadystatechange = function ()&&{&&if (objXMLHttp.readyState == 4 && (objXMLHttp.status == 200 || objXMLHttp.status == 304))&&{&&callback(objXMLHttp);&&}&&}&&}&&catch(e)&&{&&alert(e);&&}&&}&&}&&};&&&&&&&示例:&&&&&&mce:script type="text/javascript" src="xmlhttp.js" mce_src="xmlhttp.js"&&/mce:script&&&&mce:script type="text/javascript"&&!--&&function test(obj)&&{&&alert(obj.statusText);&&}&&XMLHttp.sendReq('GET', '/wp-data/test.htm', '', test);&&XMLHttp.sendReq('GET', '/wp-data/test.htm', '', test);&&XMLHttp.sendReq('GET', '/wp-data/test.htm', '', test);&&XMLHttp.sendReq('GET', '/wp-data/test.htm', '', test);&&alert('Pool length:' + XMLHttp._objPool.length);&&// --&&/mce:script&
阅读(505)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'AJAX中同时发送多个请求XMLHttpRequest对象处理方法',
blogAbstract:'
* XMLHttpRequest Object Pool&&*&&* @author legend &&&&* @link http:///?p=85&&* @Copyright &&*/&&&var XMLHttp = {&&_objPool: [],&&_getInstance: function ()&&{&&for',
blogTag:'',
blogUrl:'blog/static/9',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:9,
permalink:'blog/static/9',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}}

我要回帖

更多关于 plate load test 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信