thrift 內存溢出

短信服務,運用了thrift框架。html

thrift,是 Facebook 實現的一種高效的、支持多種編程語言的遠程服務調用的框架。而推出最初,其存在不少問題,見如下連接java

http://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/  thrift學習入門linux

http://yanyiwu.com/work/2014/10/17/thrift-source-code-illustration.html thrift源碼解析apache

http://blog.csdn.net/shijun_zhang/article/details/6863836  thrift rpc 使用常見問題解答和經驗編程

因此,thrift的client最好是以鏈接池來進行管理,防止過多的client同時請求帶來的問題。而thrift的server的選擇,則要根據要提供的服務進行選擇。數組

對應的server(java版)主要有服務器

一、TSimpleServer  通常僅做爲測試用
二、TNonblockingServer 非阻塞式,用nio進行通訊,但依然只有一個進程處理請求
三、THsHaServer   混合模式,半同步/半異步。它使用一個單獨的線程來處理網絡I/O,一個獨立的worker線程池來處理消息。
四、TThreadedSelectorServer 容許你用多個線程來處理網絡I/O。它維護了兩個線程池,一個用來處理網絡I/O,另外一個用來進行請求的處理。當網絡I/O是瓶頸的時候,        TThreadedSelectorServer比THsHaServer的表現要好
五、TThreadPoolServer 相似於線程池了,有一個專用的線程用來接受鏈接。一旦接受了一個鏈接,它就會被放入ThreadPoolExecutor中的一個worker線程裏處理。可是worker線程被綁定到特定的客戶端鏈接上,直到它關閉。
網絡

具體區別,請查看 框架

http://blog.csdn.net/azhao_dn/article/details/8898610異步

http://m.blog.csdn.net/blog/hjx_1000/42779915

 

咱們的短信服務,由於多了一家運營商,並且又分生產跟營銷不一樣的渠道,再考慮到可擴展性,即後期會加入別的運營商,因此將短信服務進行了簡單的重構。

提供兩個接口,發送營銷短信、發送生產短信,而後根據傳入的cpid(標誌着發送短信的場合),找到對應的渠道信息,再找到對應的operator,從而調用該operator對應的發送短信的方法。

未進行重構前,還一直沒關注其佔用內存狀況,也沒有報內存溢出。

重構後,一開始還比較穩定,用了幾天以後,出現了內存溢出,一直到如今,出現的愈來愈頻繁。

用 ps -aux | grep sms 查看該服務佔用內存一直增長。即便gc後,也依然減小的不多。

用 jmap -histo pid > jvm.log,打印出內存中相關的內容,

num #instances #bytes class name
----------------------------------------------
1: 2179572 34873152 java.lang.Object
2: 63701 33237280 [C
3: 242114 29053680 java.net.SocksSocketImpl
4: 241711 27071632 sun.nio.ch.SocketChannelImpl
5: 241711 11602128 sun.nio.ch.SocketAdaptor
6: 30834 7792856 [B
7: 242115 7747680 java.net.Inet4Address
8: 241712 7734784 [Ljava.nio.channels.SelectionKey;
9: 45748 6613624 <constMethodKlass>
10: 45748 6231856 <methodKlass>
11: 242580 5821920 java.io.FileDescriptor
12: 241712 5801088 java.net.InetSocketAddress
13: 3993 4316064 <constantPoolKlass>
14: 242696 3883136 java.util.concurrent.atomic.AtomicInteger
15: 241712 3867392 sun.nio.ch.OptionAdaptor
16: 241712 3867392 sun.nio.ch.SocketOptsImpl$IP$TCP
17: 241711 3867376 sun.nio.ch.SocketChannelImpl$1
18: 241264 3860224 java.nio.channels.spi.AbstractInterruptibleChannel$1
19: 69769 3599896 <symbolKlass>
20: 16811 3220440 [I

除了socket相關的,基本都是char,String,int等數組之類的。

查詢內存狀況的相關工具介紹,參考此連接 http://blog.csdn.net/zhujiongming/article/details/8510462

用jstat -gc pid,關注gc狀況,偶然間抓住了gc先後的jvm.log,進行對比後,發現socket相關的對象基本沒有減小,初步懷疑thrift基於socket通訊,沒有關閉socket?可是後臺是一個線程池,不解。還須要對thrift原理一級socket通訊原理進行學習。

後來在本地跑thrift server,沒有任何請求,佔用內存以下圖所示,頂峯時甚至達到過400-500M,並且,測試機上的thrift server也內存溢出過,請求量幾乎沒有。

thrift一直再監聽是否有請求,佔用大量內存?

能夠選擇jdk自帶的jconsole以及jvirtualvm來監控內存使用狀況,jvirtualvm能夠dump出當時內存的內容,能夠分析看到裏面具體的信息,好比String是什麼內容等。可是依然沒有收穫。

後來選用jprofiler,遠程監控服務器,須要加入以下配置-agentpath:/data/jprofiler9/bin/linux-x64/libjprofilerti.so=port=8849,這樣就能夠經過8849端口,用jprofiler客戶端遠程監控服務器的內存狀況了。

咱們也能夠加入gc日誌,分析gc狀況  -Xloggc:/data/logs/sms/gclogs/gc.log

加入堆內存溢出時,導出dump文件,保留當時內存內容 -XX:+HeapDumpOnOutOfMemoryError  -XX:HeapDumpPath=/data/logs/sms/outofmemory.hprof

jvm參數設置以及GC策略,參考此連接 http://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html ,後期須要深刻學習一下。

後來發現,報內存溢出時,400M的內存,只是佔用了幾十M?目前問題依然沒有找到。

調大短信工程佔用的內存以後,問題再沒出現過。。
相關文章
相關標籤/搜索