ActiveMQ SSL连接泄露问题记录

现象

前几日在生产环境上出现了SSL连接泄露的问题,具体现象是

  1. 客户端使用SSL协议不停尝试重连MQ,客户端上使用netstat查看,同时存在的连接数量不超过2个,但是MQ的服务器上使用netstat查看发现连接数量不断增长,且IP均为该客户端。
  2. 连接数量达到4500时发现MQ的activemq.log中出现了java.lang.OutOfMemoryError: unable to create new native thread异常,也就是堆外内存溢出。
  3. ActiveMQ页面上发现连接数量(100左右)远小于netstat查看得到的数量。
  4. MQ重启后,连接数量仍然上升,客户端修改逻辑使用failover机制而不是connection.start + stop后恢复正常。

在问题ActiveMQ中,使用的是BIO模式,也就是说每个连接使用1个线程承载。

分析

通过jstack获取到MQ重启后客户端修改前的线程日志后发现(此时连接数量约500),客户端的Transport线程为BLOCKED状态,在等待锁释放,而持有该锁的线程是ActiveMQ BrokerService线程,该线程为RUNNABLE状态,但是这个状态持续了很长时间都未释放锁。

此外BrokerService线程持有的锁还导致了另一类Inactivity Monitor Worker线程BLOCKED,这三类线程数量基本持平,都为500个左右。也就是说一个连接泄露会出现3个同时存在的线程。两个为BLOCKED状态,一个为RUNNABLE状态但长时间持有两个锁不释放。根据JVM的默认配置Xss=1MB,也就是说一个线程会占用操作系统1MB的堆外内存,当出现大量连接泄露的时候,就导致了堆外内存用尽,出现了OOM。

进一步从ActiveMQ的源码分析,BrokerService这个线程是从线程池中创建,用于连接建立时的握手等,BrokerService卡在的方法是oracle的SSL连接performInitialHandshake方法,从方法名可以看出来是SSL连接的初次协议握手。僵死的位置是SocketInputStream.socketRead0,也就是读阻塞了。
此时连接还没有完成建立,而Transport线程是BLOCKED在往OutputStream里写数据,在等待BrokerService从InputStream里读完数据;Inactivity Monitor Woker线程是BLOCKED在关闭连接的过程中,因为BrokerService线程持有了一个starting的锁,这个锁标识着连接建立是否完成。Inactivity线程发现连接建立超时了,尝试关闭的时候又发现连接仍然在建立过程中,无法关闭。

ActiveMQ默认不开启TCP KEEPALIVE机制,而是使用自己的Inactivity Monitor机制,但是未曾想Inactivity机制也被阻塞了。

   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:150)
    at java.net.SocketInputStream.read(SocketInputStream.java:121)
    at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
    at sun.security.ssl.InputRecord.read(InputRecord.java:480)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
    - locked <xxxxxxxxxxxxxxx> (a java.lang.Object)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)

接下来就是看看为啥会出现读阻塞了,其实可以看到这里阻塞的位置已经很底层了,所以可以大致考虑是触发了操作系统或者JDK的bug。看了下还真有符合的。JDK-8143992到oracle jdk底层的堆栈信息完全一样,只是这里的错误是从HTTPS中报出的,但是都是SSL协议。进一步可以看到这个BUG是【JDK-8075484】的Duplicated。

https://bugs.java.com/view_bug.do?bug_id=8075484

As noted at JDK-8049846, the implementation of Java_java_net_SocketInputStream_socketRead0 assumes that read() won't block after poll() reports that a read is possible. This assumption does not hold, as noted on the man page for select (referenced by the man page for poll): Under Linux, select() may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is discarded. There may be other circumstances in which a file descriptor is spuriously reported as ready. Thus it may be safer to use O_NONBLOCK on sockets that should not block.
大意是Linux中告诉jvm说socket文件描述符可读但是不代表这个socket一定不会阻塞,而JDK却认为一定不会阻塞。

问题解决方法:

  1. 考虑开启TCP KEEPALIVE机制看看能不能把异常连接给关了,因为肯定没有数据流了。但是Linux的TCP KEEPALIVE机制需要2个小时才会生效,所以需要调整一下KEEPALIVE机制的时间。
  2. 升级JDK到Fixed的版本。

此外还存在几个问题:

  1. 这个BUG是偶发的,但是从生产环境看,竟然变成了每次建立连接都会触发,这是为什么呢?
  2. 客户端建立连接,发送消息,关闭连接这个过程并未报错,为什么?connection.stop这个方法中可是有个向服务器同步发送关闭连接信息的动作。

嗯。。。还需要继续研究看看。。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容

  • ActiveMQ 即时通讯服务 浅析http://www.cnblogs.com/hoojo/p/active_m...
    bboymonk阅读 1,488评论 0 11
  • 个人专题目录[https://www.jianshu.com/p/140e2a59db2c] 一、JMS简介 全称...
    Java及SpringBoot阅读 2,084评论 0 10
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,652评论 18 139
  • 简介 ActiveMQ 特点 ActiveMQ 是由 Apache 出品的一款开源消息中间件,旨在为应用程序提供高...
    预流阅读 5,922评论 4 21
  • 前几天在“一块听听”中听了一堂李笑来老师的讲座,主题为《这些年我的创作经验》。该讲座重点讲了五方面内容:1.差异化...
    心诚则灵yue阅读 2,490评论 17 21