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?目前问题依然没有找到。

调大短信工程占用的内存以后,问题再没出现过。。
相关文章
相关标签/搜索