利用ab测试工具对Tornado下使用mongodb驱动的性能简单测试分析
2017-12-18 18:42
537 查看
Blog地址:https://www.jiangdog.com/blog/tornado-motor-ab
参考网上的文章并自己写了一些简单的代码来测试在使用
CentOS下安装可以参考:How to install Apache Benchmark on CentOS?,实际上就是两条命令
windows下安装:https://www.apachehaus.com/cgi-bin/download.plx 下载相应版本的apache安装包,并解压安装到指定目录。
ab基本参数介绍:
-n 指定总共发起的请求数量。
-c 同时发起的请求数量,并发请求数。
-p 指定post方式提交的数据的文件,文件内容格式为
-T 指定content-type
1核 1GB 带宽1Mbps
CentOS 7.2
mongodb和测试web服务都是安装或部署在该实例上:
mongodb 3.4
python 3.5.1
tornado 4.4.2
pymongo 3.6.0
mongoengine 0.15.0
motor 1.1
get请求查询信息列表。
post请求添加数据:
get请求数据列表:
post添加数据:
get请求数据列表:
post新增数据:
接着更改指标测试了
发现每次测试接收数据速率一直都是70kb/s左右,发现是否和带宽限制有关,改到服务器本地和内网进行简单测试。
由上述不难发现,当传输速度足够时
继续更改测试指标试图发现
值得一提的是在
考虑到很多情况下不会有这么多并发和请求,重新测试了现对较少请求和并发(
依旧是
但在使用
简单增加了一些无用的逻辑,单纯增加访问数据库的次数,再对
https://emptysqua.re/blog/introducing-motor-an-asynchronous-mongodb-driver-for-python-and-tornado/
Apache ab测试工具使用方法(无参、get传参、post传参)
tornado的mongo驱动选择,pymongo,motor,asyncmongo还是其他?
Tornado 中 PyMongo Motor MongoEngine 的性能测试,这两个测试结果,一个pymongo好,一个motor好。
相关代码
背景
在利用Python开发web项目时,可以使用pymongo、
mongoengine等库连接mongodb。当使用
Tornado框架时,为了利用其异步的特性,还可以使用
motor来作为数据库驱动。无论是
mongoengine还是
motor实际上应该都是对
pymongo的封装。
mongoengine提供了ORM映射的功能,将
Document封装成类,通过实例的方法来操作
Document。
motor能够和
Tornado或协程配合使用,异步调用提升性能。
参考网上的文章并自己写了一些简单的代码来测试在使用
Tornado框架下,这三种数据库驱动的性能。
测试工具
使用ab来做这次简单测试。
CentOS下安装可以参考:How to install Apache Benchmark on CentOS?,实际上就是两条命令
yum provides /usr/bin/ab yum install httpd-tools
windows下安装:https://www.apachehaus.com/cgi-bin/download.plx 下载相应版本的apache安装包,并解压安装到指定目录。
ab基本参数介绍:
-n 指定总共发起的请求数量。
-c 同时发起的请求数量,并发请求数。
-p 指定post方式提交的数据的文件,文件内容格式为
a=1&b=2。
-T 指定content-type
测试服务器配置及环境
服务器是利用了阿里云的基本的云服务器ECS实例:1核 1GB 带宽1Mbps
CentOS 7.2
mongodb和测试web服务都是安装或部署在该实例上:
mongodb 3.4
python 3.5.1
tornado 4.4.2
pymongo 3.6.0
mongoengine 0.15.0
motor 1.1
编写简单的服务端代码并利用ab进行测试
pymongo:
#!/usr/bin/python # -*- coding:utf-8 -*- import tornado.web import tornado.gen from pymongo import MongoClient from tornado.httpserver import HTTPServer class MessageListHandler(tornado.web.RequestHandler): def get(self): message_list = self.settings['db'].messages.find().sort([('_id', -1)]).limit(50) self.render('msg_list.html', message_list=message_list) class MessageAddHandler(tornado.web.RequestHandler): def get(self): self.render('msg_add.html') def post(self): msg = self.get_argument('msg') res = self.settings['db'].messages.insert_one({'msg': msg}) self.redirect('/message/list/') class Application(tornado.web.Application): def __init__(self): handlers = [ (r'/message/list/', MessageListHandler), (r'/message/add/', MessageAddHandler), ] db = MongoClient('mongodb://127.0.0.1:27017', maxPoolSize=200).test_motor settings = dict( db=db, debug=False, ) tornado.web.Application.__init__(self, handlers, **settings) def main(): app = Application() httpserver = HTTPServer(app, xheaders=True) httpserver.listen(80) tornado.ioloop.IOLoop.instance().start() if __name__ == '__main__': main()
get请求查询信息列表。
post请求添加数据:
mongoengine:
#!/usr/bin/python # -*- coding:utf-8 -*- import tornado.web import tornado.gen from mongoengine import Document, StringField, connect from tornado.httpserver import HTTPServer class Messages(Document): msg = StringField(required=True) class MessageListHandler(tornado.web.RequestHandler): def get(self): message_list = Messages.objects.filter().order_by('-id').limit(50) self.render('msg_list.html', message_list=message_list) class MessageAddHandler(tornado.web.RequestHandler): def get(self): self.render('msg_add.html') def post(self): msg = self.get_argument('msg') res = Messages(msg=msg).save() self.redirect('/message/list/') class Application(tornado.web.Application): def __init__(self): handlers = [ (r'/message/list/', MessageListHandler), (r'/message/add/', MessageAddHandler), ] connect('test_motor', host='127.0.0.1', port=27017, maxPoolSize=200) settings = dict( debug=False, ) tornado.web.Application.__init__(self, handlers, **settings) def main(): app = Application() httpserver = HTTPServer(app, xheaders=True) httpserver.listen(80) tornado.ioloop.IOLoop.instance().start() if __name__ == '__main__': main()
get请求数据列表:
post添加数据:
motor:
#!/usr/bin/python # -*- coding:utf-8 -*- import motor import tornado.web import tornado.gen from tornado.httpserver import HTTPServer class MessageListHandler(tornado.web.RequestHandler): @tornado.gen.coroutine def get(self): message_list = yield self.settings['db'].messages.find().sort([('_id', -1)]).limit(50).to_list(length=None) self.render('msg_list.html', message_list=message_list) class MessageAddHandler(tornado.web.RequestHandler): def get(self): self.render('msg_add.html') @tornado.gen.coroutine def post(self): msg = self.get_argument('msg') res = yield self.settings['db'].messages.insert_one({'msg': msg}) self.redirect('/message/list/') class Application(tornado.web.Application): def __init__(self): handlers = [ (r'/message/list/', MessageListHandler), (r'/message/add/', MessageAddHandler), ] db = motor.motor_tornado.MotorClient('mongodb://127.0.0.1:27017', maxPoolSize=200).test_motor settings = dict( db=db, debug=False, ) tornado.web.Application.__init__(self, handlers, **settings) def main(): app = Application() httpserver = HTTPServer(app, xheaders=True) httpserver.listen(80) tornado.ioloop.IOLoop.instance().start() if __name__ == '__main__': main()
get请求数据列表:
post新增数据:
分析相关的测试数据
由上述简单测试不难发现,在n1000c200(总请求1000,并发200)的情况下各项测试数据相差并不是很大。
接着更改指标测试了
n5000c500和
n8000c8000,发现依旧差异不大,自认为再测下去也没什么意义。
发现每次测试接收数据速率一直都是70kb/s左右,发现是否和带宽限制有关,改到服务器本地和内网进行简单测试。
n1000c200:
pymongo:
mongoengine:
motor:
由上述不难发现,当传输速度足够时
mongoengine相比起
pymongo和
motor的处理性能下降了很多很多。
继续更改测试指标试图发现
pymongo和
motor的差异。
n5000c500:
pymongo:
motor:
值得一提的是在
ab进行
n5000c500测试的时候,使用
pymongo时经常会出现
apr_socket_recv: Connection reset by peer (104)错误,且更大数量级请求和并发时一直出现导致所有请求无法完成,查了资料也没能解除这个限制;但在使用
motor时,基本没有出现这个错误信息,且对于
n8000c800也能正常测试,如下图。
考虑到很多情况下不会有这么多并发和请求,重新测试了现对较少请求和并发(
n1000c50等)的情况。
pymongo:
mongoengine:
motor:
依旧是
pymongo和
motor表现的出色,
mongoengine感觉差了一个档次。
End
不管是在请求总量较少并发量小(如总请求1000,并发50、甚至总请求200,并发20)的情况下,pymongo和
motor始终比
mongoengine表现的出色。使用
pymongo和
motor服务器处理每次请求的速度甚至比
mongoengine快一倍,QPS和用户平均等待时间也相差很多。
但在使用
mongoengine编写代码时,提供了现成的类似ORM的作用,可能编写代码相对较为方便;而
pymongo原生的始终是通过字典来操作的;
motor也是通过字典切需要结合
tornado的异步特性来使用。
pymongo和
motor在上述较少数据量简单测试代码是表现的都很出色,相差不大(或者在相对少请求量和并发时,
pymongo比
motor略微好一点点),但在请求量很大并发大时,由于一些未能解决的错误,没有进行很好的完整的测试。之后可能需要添加更加复杂的逻辑代码,可能需要增大数据量,增加每次请求中访问数据库的次数,理论上应该
motor会表现的更好。
简单增加了一些无用的逻辑,单纯增加访问数据库的次数,再对
pymongo和
motor进行一些测试。
class MessageListHandler(tornado.web.RequestHandler): def get(self): # message_list = self.settings['db'].messages.find().sort([('_id', -1)]).limit(50) # message_list = self.settings['db'].messages.find().sort([('_id', -1)]).limit(500) message_list = [] for i in range(10): message_list.extend(self.settings['db'].messages.find().sort([('_id', -1)]).limit(50)) self.render('msg_list.html', message_list=message_list)
class MessageListHandler(tornado.web.RequestHandler): @tornado.gen.coroutine def get(self): # message_list = yield self.settings['db'].messages.find().sort([('_id', -1)]).limit(50).to_list(length=None) # message_list = yield self.settings['db'].messages.find().sort([('_id', -1)]).limit(500).to_list(length=None) message_list = [] for i in range(10): temp_list = yield self.settings['db'].messages.find().sort([('_id', -1)]).limit(50).to_list(length=None) message_list.extend(temp_list) self.render('msg_list.html', message_list=message_list)
motor反而处理性能变的更差了。
参考链接:
What are the Tornado and Mongodb blocking and asynchronous considerations?https://emptysqua.re/blog/introducing-motor-an-asynchronous-mongodb-driver-for-python-and-tornado/
Apache ab测试工具使用方法(无参、get传参、post传参)
tornado的mongo驱动选择,pymongo,motor,asyncmongo还是其他?
Tornado 中 PyMongo Motor MongoEngine 的性能测试,这两个测试结果,一个pymongo好,一个motor好。
后续
重新在公司内部测试服务器(具体配置未知,但配置肯定比之前的阿里云高)用python 2.7进行了测试,测试代码也进行了稍作优化,增加了一定的业务逻辑,同时利用mongostat简单监测了mongodb的各项数据,结果发现
motor框架在高并发,操作数据库代码较多时,表现的性能更好。
相关代码
相关文章推荐
- 使用LoadRunner进行性能测试的简单步骤
- gprof性能测试工具使用分析
- 在C/C++代码中使用SSE等指令集的指令(5)SSE进行加法运算简单的性能测试
- 转-MongoDB、HandlerSocket和MySQL性能测试及其结果分析
- 使用Oprofile分析性能瓶颈--简单例子
- MongoDB、HandlerSocket和MySQL性能测试及其结果分析
- [原创]MongoDB、HandlerSocket和MySQL性能测试及其结果分析
- C++简单测试MongoDB性能
- 十分简单的redis使用说明及性能测试
- 使用erlang实现简单的http性能测试工具,替代loadrunner、loadspace
- 简单的redis使用说明及性能测试
- 使用AOP,在spring中实现简单的性能测试
- 在C/C++代码中使用SSE等指令集的指令(5)SSE进行加法运算简单的性能测试
- MongoDB、HandlerSocket和MySQL性能测试及其结果分析
- 在C/C++代码中使用SSE等指令集的指令(5)SSE进行加法运算简单的性能测试
- MongoDB和MySQL HandlerSocket性能测试及其结果分析
- 使用分析函数和不使用分析函数的性能对比测试
- 开源性能测试工具--Jmeter简单使用
- MongoDB、HandlerSocket和MySQL性能测试及其结果分析
- [网页性能分析]利用Firfox,firbug,cssusage来分析CSS在网页中使用覆盖率