• thrift 内存溢出


    短信服务,运用了thrift框架。

    thrift,是 Facebook 实现的一种高效的、支持多种编程语言的远程服务调用的框架。而推出最初,其存在很多问题,见以下链接

    http://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/  thrift学习入门

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

    http://blog.csdn.net/shijun_zhang/article/details/6863836  thrift rpc 使用常见问题解答和经验

    所以,thrift的client最好是以连接池来进行管理,防止过多的client同时请求带来的问题。而thrift的server的选择,则要根据要提供的服务进行选择。

    对应的server(java版)主要有

    1、TSimpleServer  一般仅作为测试用
    2、TNonblockingServer 非阻塞式,用nio进行通信,但依然只有一个进程处理请求
    3、THsHaServer   混合模式,半同步/半异步。它使用一个单独的线程来处理网络I/O,一个独立的worker线程池来处理消息。
    4、TThreadedSelectorServer 允许你用多个线程来处理网络I/O。它维护了两个线程池,一个用来处理网络I/O,另一个用来进行请求的处理。当网络I/O是瓶颈的时候,        TThreadedSelectorServer比THsHaServer的表现要好
    5、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?目前问题依然没有找到。

    调大短信工程占用的内存之后,问题再没出现过。。
  • 相关阅读:
    java 数据结构(一):java常用类 一 String类
    java 数据结构(三):java常用类 三 日期时间API
    java 数据结构(四):java常用类四 比较器以及其他类
    java 数据结构(五):数据结构简述
    Android开发 无法导入ViewPagerIndicator或其他开源框架无法导入
    开源控件ViewPagerIndicator的使用
    Android简易实战教程--第二十五话《网络图片查看器》
    The type org.apache.http.HttpResponse cannot be resolved. It is indirectly referenced from required
    Mac 下安装node.js
    Android简易实战教程--第二十四话《画画板》
  • 原文地址:https://www.cnblogs.com/govoid/p/5020233.html
Copyright © 2020-2023  润新知