自定义创建rabbitMQ的channel连接池

参考地址:https://blog.csdn.net/qq447995687/article/details/80233621

利用commons-pool2自定义对象池
commons-pool2是Apache下一个开源的公共资源池。我们可以根据它来快速的建立一个自己的对象池。

commons-pool2包下载地址https://pan.baidu.com/s/1lVUX_FZAbKjW87jTGJ_Rmw
密码:a8d0

1.创建连接池工厂,实现PooledObjectFactory接口

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.tds.smgw.util.Environment;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 1. 自定义连接池工厂
 **/
public class RabbitMqChannelPoolFactory implements PooledObjectFactory<Channel> {

    private Connection connection;

    public RabbitMqChannelPoolFactory(){
        try {
            //创建连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            //设置host
            factory.setHost("127.0.0.1");
            factory.setPort(5672);
            factory.setUsername("test");
            factory.setPassword("test");
            factory.setVirtualHost("/");
            factory.setConnectionTimeout(15000);
            connection = factory.newConnection();
        } catch (IOException | TimeoutException e) {
            e.printStackTrace();
        }
    }

    @Override
    public PooledObject<Channel> makeObject() throws Exception {
        // 池对象创建实例化资源
        return new DefaultPooledObject<>(connection.createChannel());
    }

    @Override
    public void destroyObject(PooledObject<Channel> p) throws Exception {
        // 池对象销毁资源
        if (p != null && p.getObject() != null && p.getObject().isOpen()) {
            p.getObject().close();
        }
    }

    @Override
    public boolean validateObject(PooledObject<Channel> p) {
        // 验证资源是否可用
        return p.getObject() != null && p.getObject().isOpen();
    }

    @Override
    public void activateObject(PooledObject<Channel> p) {

    }

    @Override
    public void passivateObject(PooledObject<Channel> p) {

    }
}

2.创建连接池,实现GenericObjectPool接口

import com.rabbitmq.client.Channel;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.AbandonedConfig;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

/**
 1. 自定义连接池
 **/
public class RabbitMqChannelPool extends GenericObjectPool<Channel> {

    public RabbitMqChannelPool(PooledObjectFactory<Channel> factory) {
        super(factory);
    }

    public RabbitMqChannelPool(PooledObjectFactory<Channel> factory, GenericObjectPoolConfig config) {
        super(factory, config);
    }

    public RabbitMqChannelPool(PooledObjectFactory<Channel> factory, GenericObjectPoolConfig config, AbandonedConfig abandonedConfig) {
        super(factory, config, abandonedConfig);
    }
}

3.获取和关闭channel连接

import com.rabbitmq.client.Channel;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

/**
 * channel管理
 **/
public class RabbitMqChannelService {

    private RabbitMqChannelPool pool;

    public static RabbitMqChannelService getInstance() {
        return SingletonHolder.INSTANCE;
    }

    /**
     * 获取channel对象
     * pool.borrowObject()是线程安全的
     *
     * @return 结果
     * @throws Exception 异常
     */
    public Channel getChannel() throws Exception {
        return pool.borrowObject();
    }

    /**
     * 归还channel对象
     *
     * @param channel 结果
     */
    public void returnChannel(Channel channel) {
        pool.returnObject(channel);
    }

    private static class SingletonHolder {
        private final static RabbitMqChannelService INSTANCE = new RabbitMqChannelService();
    }

    private RabbitMqChannelService() {
        initPool();
    }

    /**
     * 初始化pool
     */
    private void initPool() {
        RabbitMqChannelPoolFactory factory = new RabbitMqChannelPoolFactory();
        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        // 设置最大连接数
        config.setMaxTotal(300);
        // 最大空闲连接数
        config.setMaxIdle(20);
        // 最小空闲连接数
        config.setMinIdle(10);
        // 空闲连接检测周期
        config.setTimeBetweenEvictionRunsMillis(6000);
        // 达到此空闲时间后,连接将被移除
        config.setSoftMinEvictableIdleTimeMillis(20000);
        // 连接资源耗尽后最大等待时间
        config.setMaxWaitMillis(10000);

        pool = new RabbitMqChannelPool(factory, config);
    }
}

4.生产者

import com.rabbitmq.client.Channel;
import org.apache.commons.lang.SerializationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;

/**
 * rabbit消息发送
 */
public class RabbitMqProducer {

    private Logger logger = LoggerFactory.getLogger(RabbitMqProducer.class);

    private String queueName;

    public RabbitMqProducer(String queueName) {
        this.queueName = queueName;
    }

    /**
     * 发送信息
     *
     * @param obj 发送的内容
     */
    public void sendMessage(Serializable obj) {
        RabbitMqChannelService rabbitMqChannelService = RabbitMqChannelService.getInstance();
        Channel channel = null;
        try {
            channel = rabbitMqChannelService.getChannel();
            // 为这个通道申明一个队列,如果这个队列不存在,他将在服务器上创建
            channel.queueDeclare(queueName, true, false, false, null);
            channel.basicPublish("", queueName, null, SerializationUtils.serialize(obj));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (null != channel) {
                rabbitMqChannelService.returnChannel(channel);
            }
        }
    }
}

5.消费者,实现Consumer接口

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.ShutdownSignalException;
import com.tds.smgw.service.impl.RabitMqService;
import com.tds.smgw.util.Environment;
import org.apache.commons.lang.SerializationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * 消费者
 * 这里channel和Consumer是一对一
 * 使用消息自动确认机制
 */
public class RabbitMqConsumer implements Consumer {

    private static Logger logger = LoggerFactory.getLogger(RabbitMqConsumer.class);
	
	private static String queueName;

    private static RabitMqService rabitMqService;

    private Channel channel;

    private RabbitMqConsumer() {
        init();
    }

    private static class SingletonHolder {
        private static final RabbitMqConsumer INSTANCE = new RabbitMqConsumer();
    }

    public static RabbitMqConsumer getInstance(String queueName) {
        if (null == RabbitMqConsumer.queueName) {
            RabbitMqConsumer.queueName = queueName;
        }

        return SingletonHolder.INSTANCE;
    }

    /**
     * 设置接收消息queue
     */
    private void init() {
        try {
            channel = RabbitMqChannelService.getInstance().getChannel();
            logger.info("启动RabbitMq监听器:" + channel + "监听QUEUE【" + queueName + "】");
            // 为这个通道申明一个队列,如果这个队列不存在,他将在服务器上创建,防止不存在时报错
            channel.queueDeclare(queueName, true, false, false, null);
            // 开启接收信息,自动确认
            channel.basicConsume(queueName, true, this);
            // 开启接收信息,手动确认
            // channel.basicConsume(queueName, false, this);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (null != channel) {
                logger.info("channel ---》" + channel);
                // 不能归还,归还后有可能被关闭导致消费者阻塞
//                rabbitMqChannelService.returnChannel(channel);
            }
        }

    }

    /**
     * 当用户注册时调用
     */
    @Override
    public void handleCancelOk(String consumerTag) {
        System.out.println("Consumer " + consumerTag + " registered");
    }

    /**
     * 当有可用新消息时调用
     */
    @Override
    @SuppressWarnings("unchecked")
    public void handleDelivery(String consumerTag, Envelope env, BasicProperties props, byte[] body) {
        logger.info("------------------------------[{}]MQ监听器执行开始[{}]---------------------------"
                , env.getRoutingKey(), System.currentTimeMillis());
        Map<String, String> map = (HashMap<String, String>) SerializationUtils.deserialize(body);
        logger.info("接收消息:" + SerializationUtils.deserialize(body));
        //     channel.basicAck(env.getDeliveryTag(), false);
        logger.info("------------------------------[{}]MQ监听器执行结束[{}]---------------------------"
                , env.getRoutingKey(), System.currentTimeMillis());
    }

    @Override
    public void handleCancel(String consumerTag) {
    }

    @Override
    public void handleConsumeOk(String consumerTag) {
    }

    @Override
    public void handleRecoverOk(String consumerTag) {
    }


    @Override
    public void handleShutdownSignal(String consumerTag, ShutdownSignalException arg1) {
    }
}

6.测试

   public static void main(String[] args) {
        String queueName = "testQueue";
        // 需要提前启动消费者监听queue,否则监听不到生产者生产的消息
        RabbitMqConsumer.getInstance(queueName);
        // 启动rabbitMq生产者
        RabbitMqProducer producer = new RabbitMqProducer(queueName);
        Map<String, String> map = new HashMap<>(16);
        map.put("date", "date");
        map.put("time", "time");
        map.put("userId", "userId");
        producer.sendMessage((Serializable) map);
    }
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值