• 单例模式解决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正常使用。
  • 相关阅读:
    Spring Boot2(九):整合Jpa的基本使用
    Spring Boot2(八):性感banner,在线发牌
    Spring Boot2(七):拦截器和过滤器
    我为什么要写作
    代码整洁之道
    redis-缓存穿透和缓存击穿
    云计算的三种服务模式
    java-泛型
    java-注解
    java-反射
  • 原文地址:https://www.cnblogs.com/monkjavaer/p/9610712.html
Copyright © 2020-2023  润新知