使用阿里云消息队列踩了个坑

背景:公司产品需要做微信服务,了解的人都知道微信粉丝有交互就会给第三方平台推送事件消息。也就是说产品管理的公众号越多,公众号的粉丝越多,那么平台需要处理的事件消息也就会越频繁。于是想到用MQ解决压力问题。自己搭建MQ维护成本又高,自然而然的想到阿里云。

具体的详细介绍,官方帮助都有说明:

https://help.aliyun.com/document_detail/29532.html?spm=5176.doc29532.6.539.rompTV

接入方式有三种:TCP、HTTP、MQTT。考虑到实时性,我采用的是TCP普通消息接入。

然后创建 Topic 创建、Producer ID、创建 Consumer ID、创建阿里云 AccessKey,SecretKey。

接下来就是按照DEMO引入JAR包,进行开发,测试,上线。(没有很好的测试条件,没有进行压测)

上线后发现过一段时间服务器CPU使用率就会暴增,直至无响应。重启后情况依旧,郁闷了。。。。。。

经过查看堆栈等一系列跟踪排错,发现有很多thread在进行空等待,类似于下面的信息

"ConsumeMessageThread_13" daemon prio=10 tid=0x00007ff57c018000 nid=0x1fdf waiting on condition [0x00007ff52d8d7000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000007035c4f30> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
	at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)

利用Jmeter进行模拟发现,每一个消息生产、消费的过程,都要产生10多个thread,线程数在无限增长,JVM也不进行回收,直至CPU无响应。

产生原因:由于轻信了DEMO中的producer的shutdown()方法

// 在应用退出前,销毁Producer对象<br>
// 注意:如果不销毁也没有问题
producer.shutdown();

所以每当生产一个消息的时候,我就会新创建一个producer实例。而每个producer实例又会产生多个thread,数量在5-20左右(取决于自己的配置情况)。虽然调用了shutdown()方法,但是实际上,producer实例和其产生的thread并没有回收掉,thread都将进入上面描述的空等待状态。

解决方法:其实很简单,在创建Producer实例发送消息的时候,使用单例模式。(撞墙,万万没想到啊)

转载于:https://my.oschina.net/u/265896/blog/827307

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值