单例模式解决RabbitMQ超出最大连接问题
今天在项目稳定性测试过程中遇到一个情景:通过工具jMeter一直请求消息转发服务器,消息转发服务器再向rabbitMQ发送数据,在这期间出现了问题、MQ意外宕机。
1. 查看rabbitMQ管理界面。如下图、rabbitMQ连接数不断往上涨。
2.初步定为为代码问题、通过分析工具代码发现:
public class MQSender extends BaseEndPoint { public MQSender(String endPointName) throws IOException{ super(endPointName); } public void sendMessage(Serializable object) throws IOException { if (channel != null) { channel.basicPublish("", endPointName, MessageProperties.PERSISTENT_TEXT_PLAIN, SerializationUtils.serialize(object)); } } }
项目中每次在调用时:
MQSender mqSender = new MQSender(EnvConstant.NODE_PASS_QUEUE_NAME);
通过代码不难发现mq的连接会最终撑爆,再通过linux命令nohup确定jar包错误:
java.util.concurrent.TimeoutException at com.rabbitmq.utility.BlockingCell.get(BlockingCell.java:77) at com.rabbitmq.utility.BlockingCell.uninterruptibleGet(BlockingCell.java:111) at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:37) at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:367) at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:293) at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:678) at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:722
3.解决:通过单例模式改造
用“双重检查加锁”改造后的工具类:
/** * 用“双重检查加锁”,getMqSender()中减少使用同步 * 利用双重检查加锁,首先检查是否实例已经创建,如果没有才同步。 * 这样只有第一次才会同步。 * @author monkjavaer * @date 2018/08/27 22:28 */ public class MQSender extends BaseEndPoint { private volatile static MQSender mqSender; public static MQSender getMqSender(String endPointName) throws IOException { //如果实例不存在,进入同步区 if (mqSender == null){ //只有第一次才执行 synchronized (MQSender.class){ //进入区块再检查一次 if (mqSender == null){ mqSender =new MQSender(endPointName); } } } return mqSender; } private MQSender(String endPointName) throws IOException{ super(endPointName); } public void sendMessage(Serializable object) throws IOException { if (channel != null) { channel.basicPublish("", endPointName, MessageProperties.PERSISTENT_TEXT_PLAIN, SerializationUtils.serialize(object)); } } }
通过改写后mq正常使用。