openfire mysql 转mongo 注册行为性能测试及其他

测试同学使用tsung测试openfire时发现注册并发数过低,同事经过测试认为数据库是最大瓶颈,建议将mysql数据库改造成mongo数据库。


首先尝试改造了ofUser表相关操作,使注册逻辑整体走mongo:

改造涉及文件如下:

在org.jivesoftware.database 包下仿照DefaultConnectionProvider、DbConnectionManager创建mongo的相关Provider和Manager

为了减轻字段映射压力,使用了morphia,因此,需要创建相应的pojo,如ofUser.java

改造所有涉及ofUser表的增删改查


由于原来为了适应多种数据库,所以在其中增加了很多判断,搞明白逻辑后可以去除这些判断。

mongo连接方面参考了以下文章:

http://www.linuxidc.com/Linux/2012-01/52150.htm

http://www.cnblogs.com/huangfox/archive/2012/04/01/2428947.html

http://blog.csdn.net/magicfoxhu/article/details/7568728

openfire数据库相关参考了下面的文章:

http://www.myexception.cn/database/1249683.html

mongo的api及文档:

http://api.mongodb.org/java/2.8.0/

http://docs.mongodb.org/manual/genindex/

java操作mongo:

http://www.cnblogs.com/hoojo/archive/2011/06/02/2068665.html

http://tech.it168.com/a2011/0617/1206/000001206231_all.shtml

http://blog.sina.com.cn/s/blog_5d3241cc0100q7yp.html

http://www.2cto.com/database/201202/118157.html

http://www.cnblogs.com/yuechaotian/archive/2013/02/04/2891416.html

http://blog.csdn.net/mengxiangyue/article/details/8957085

使用morphia:
http://my.oschina.net/u/142072/blog/35714

http://wenku.baidu.com/view/83b56947a8956bec0975e357.html

http://www.blogjava.net/watchzerg/archive/2012/09/20/388109.html

http://www.cnblogs.com/hoojo/archive/2012/02/17/2355384.html

在寻找的时候还发现了个特好玩的morphia使用者:

https://github.com/turbidsoul/turbidsoul.github.io/commit/fe4bcdc7238b24ed06aaf327e3470ced676d1b27

在做pojo的时候特意研究了下objectid呀~发现了很多好东东哦~

http://www.cnblogs.com/xjk15082/archive/2011/09/18/2180792.html

http://www.kuqin.com/database/20120317/319007.html

http://blog.nosqlfan.com/html/3511.html

——————————————分割线————————————————————————————————————————————————————————

改造完成开始性能测试:
使用tsung测试:500请求/s 运行5分钟

数据库插入数/理论插入数,

mysql注册基本稳定在75%

mongo注册基本稳定在30%!!!!

震惊了我,mongo的性能怎么可能这么差!!

赶紧查查mongo性能提升相关的文档:

http://database.51cto.com/art/201109/293088.htm

第一条:是否建立索引,果然,我并没有建立索引,而在注册时需要先查一下此用户是否存在再进行插入,查询对索引需求大,建立索引,参考如下文档:

http://blog.sina.com.cn/s/blog_af52238c0101bhno.html

建立username索引,再次测试:

mongo注册率稳定在76%

松了一口气,但是只币mysql高1%,这可不行,开始监控mongo性能,参考:

http://www.361way.com/mongo-mem/1489.html

http://www.cnblogs.com/shanyou/archive/2010/10/02/1841348.html

http://blog.csdn.net/liubo2012/article/details/8203751

发现mongo一直处于非繁忙状态,高并发行为并没有对其产生压力。只有少数insert方法执行速度超过10ms,但是数量极少

怀疑代码或者测试工具有问题,修改代码:

(1)去除逻辑中的query妹纸保留insert,性能没有提升--》性能与query无关

(2)关闭性能监控,性能没有提升--》性能与性能监控无关

(3)删除索引,性能没有提升--》性能与索引无关

(4)不使用morphia方法使用driver自带方法--》性能没有提升,与morphia方法无关

(5)去除db重连逻辑--》性能没有提升,与此逻辑无关

(6)使用morphia save方法,每1000个注册请求,调用一次--》性能下降,原因:morphia.save并非调用批量方法,积攒1000个请求在使用此方法依旧是一个个插入,反而增大了压力。解决:改造成driver自带insert 批量插入方法,上升至76%,--》与批量无关,但是批量插入的确比单个效果更好,(貌似批量操作会有全局锁问题,需要查看http://blog.chinaunix.net/uid-26660567-id-4106642.html)

(7)增大客户端单机连接数,20改为400,性能无明显变化,查询资料:http://blog.csdn.net/jollyjumper/article/details/8553307,增加连接数反而可能使性能下降。




--依旧原因未知,实验mongo shell循环插入10w条。参考:

http://www.myexception.cn/other-database/383981.html

10w条用时40s,监控mongo性能,返现在使用mongo shell循环插入10w条时压力比tsung 500 并发高。再次确定mongo应对压力无问题。

无法,开始使用笨办法:查看数据库数据,希望能行数据中找到缺失规律,还真被我找到了!!--

插入6000条数据,前5335条插入无丢失,只丢失5336-6000的数据。推测一定不是并发造成的丢失。

在代码逻辑的insert语句前打印日志,与数据库数据进行对比,发现日志打印数与插入数据库数完全相同,再次确认与数据库无关,推测可能是自行修改的mongo逻辑和mysql逻辑不通导致,测试mysql逻辑,发现打印日志数与插入数据库数依旧相同---》确定数据库绝对无压力。

————————————————————————————我是无奈的分割线————————————————————————————————

忽然被告知,测试同学配置的tsung有问题。啊啊啊啊啊啊啊==。。。明天使用同事自己做的压测工具。。


其他参考文档:

关于Mysql和Mongo的性能测试

 http://blog.sina.com.cn/s/blog_591888d50101jx67.html

Openfire 性能优化 http://blog.csdn.net/blade2001/article/details/9094331

java链接mongo   http://blog.csdn.net/freebird_lb/article/details/7470384

________第二天的分割线——————————————————————————————

使用了asmack组件提供的接口,瞬间创建多线程施压测试,测试环境(Intel(R) Xeon(R) CPU 2.13GHz  ,内存:4139668 kB,64位)

mongo最长消耗时间是mysql最长消耗时间的2/5左右。

mongo在高并发注册情况下,成功率远高于mysql,具体数据如下:

数据库类型 方式 总发送请求数 失败数 请求完成时长 成功数 总实时长 每秒完成数 备注
Mongo 10000线程,每个线程发送2次请求 20000 0 48001 20000 8650492 416.6579863
Mongo 20000线程,每个线程发送1次请求 20000 0 49708 20000 6905026 402.3497224
Mongo 30000线程,每个线程发送1次请求 30000 0 72908 30000 12203271 411.4774785
Mongo 38000线程,每个线程发送1次请求 38000 1391 99858 36609 20398798 366.610587
Mongo 38000线程,每个线程发送1次请求 38000 0 88637 38000 12488874 428.7148708
Mongo 385线程,每个线程发送100次请求 38500 0 88597 38500 32518607 434.55196
Mongo 385线程,每个线程发送100次请求 38500 0 89802 38500 32518607 428.7209639
Mongo 3850线程,每个线程发送10次请求 38500 1878 99142 36622 36155249 369.3893607
Mongo 3850线程,每个线程发送10次请求 38500 0 85427 38500 29957272 450.6771864
Mongo 38500线程,每个线程发送1次请求 38500 0 90267 38500 15107830 426.5124575
Mongo 38500线程,每个线程发送1次请求 38500 0 89531 38500 12403008 430.0186528
415.0619297 平均值



所有mongo请求不成功问题都是由于以下问题造成的
错误:
Nested Exception:
java.net.NoRouteToHostException: Cannot assign requested address
         at java.net.PlainSocketImpl.socketConnect(Native Method)
         at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
         at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
         at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
         at java.net.Socket.connect(Socket.java:529)
         at java.net.Socket.connect(Socket.java:478)
         at org.jivesoftware.smack.proxy.DirectSocketFactory.createSocket(DirectSocketFactory.java:28)
         at org.jivesoftware.smack.XMPPConnection.connectUsingConfiguration(XMPPConnection.java:555)
         at org.jivesoftware.smack.XMPPConnection.connect(XMPPConnection.java:999)
         at Main.runRegisterTest(Main.java:54)
         at Main$3.run(Main.java:402)

原因:由于快速创建连接,端口被占用满,产生TIME_WAIT 端口
解决方案:http://bbs.chinaunix.net/thread-3842444-1-1.html
不能确定影响范围,暂时不进行解决
第二解决方案:
研究发现,Linux对外的随机分配端口是由一定限制的,理论上单机对外的端口最大值为65535,除去一些保留端口和被占用端口外,也应该在6W左右,但实际上单机建立对外连接时,默认不超过28232个连接。
    执行以下命令就很清楚原因了:
    $ cat /proc/sys/net/ipv4/ip_local_port_range
输出结果为:
    32768   61000
    这就是Linux随机分配端口的范围,如果在该范围内有被占用的端口,那么连接数肯定小于28232.如果想更改这个范围,可以执行以下命令:
    # echo "10000 65535" > /proc/sys/net/ipv4/ip_local_port_range


检测发现Mongo性能情况一直良好,基本无等待队列产生


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章