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性能情況一直良好,基本無等待隊列產生


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