动态注册卸载RabbitMq队列和监听

  • 需求: 需求中会有插件的动态安装和卸载,需求需要安装一个插件动态的创建(初始化MQ的队列),并同时对初始化的队列设置MQ的消费监听,卸载一个插件的时候会动态删除MQ的队列,并卸载掉MQ的队列的消费监听

  • 创建MQ队列使用RabbitAdmin

  • MQ的消费监听动态手动注册bean,一个消费监听注册一个新的bean,就是多个不同的MQ队列消费是不同的bean,这样做有利于MQ消费的速率,都是一个bean消费所有的MQ队列,消费速率提不上去。

  • MQ的配置类

java 复制代码
@Slf4j
@Configuration
public class RabbitMqConfig implements BeanFactoryAware {

    @Resource
    private ConnectionFactory connectionFactory;
    private DefaultListableBeanFactory beanFactory;


    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        if (beanFactory instanceof DefaultListableBeanFactory) {
            this.beanFactory = (DefaultListableBeanFactory) beanFactory;
        }
    }

    @Bean
    public RabbitAdmin rabbitAdmin() {
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
        rabbitAdmin.setAutoStartup(true);
        return rabbitAdmin;
    }

    @Bean
    @ConditionalOnMissingBean(MessageConverter.class)
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

   @Bean
    DirectExchange pluginExchange() {
        return new DirectExchange("plugin-queue-exchange");
    }

}
  • MQ队列的初始化,卸载类
typescript 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.stereotype.Service;
import webber.aiservice.processer.mq.entity.RabbitMq;
import webber.aiservice.processer.mq.listener.PluginQueueListener;

import javax.annotation.Resource;


@Service
@Slf4j
public class PluginQueueService implements BeanFactoryAware {
    @Resource
    private RabbitAdmin rabbitAdmin;

    @Resource
    private DirectExchange pluginExchange;

    @Resource
    private ConnectionFactory connectionFactory;
    
    private DefaultListableBeanFactory beanFactory;
    
    @Resource
    private PluginQueueListener pluginQueueListener;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        if (beanFactory instanceof DefaultListableBeanFactory) {
            this.beanFactory = (DefaultListableBeanFactory) beanFactory;
        }
    }


    /**
     * 初始化队列、交换机、监听
     *
     * @param queueName    队列名称
     * @param key          绑定KEY
     * @author leixiaohong
     */
    public void initMq(String queueName, String key) {
        //自动初始化监听
        registerListener(queueName, key);
    }

    /**
     * 删除队列和交换机
     *
     * @param queueName 队列名称
     * @author leixiaohong
     */
    public void deleteMq(String queueName, String routingKey) {

        //删除监听
        removeListener(queueName, routingKey);
        deleteQueue(queueName);
    }



    /**
     * 初始化队列
     *
     * @author leixiaohong
     */
    private void registerListener(String queueName, String routingKey) {
        Queue queue = QueueBuilder.durable(queueName).build();
        rabbitAdmin.declareExchange(pluginExchange);
        rabbitAdmin.declareQueue(queue);
        rabbitAdmin.declareBinding(BindingBuilder.bind(queue).to(pluginExchange).with(routingKey));
        
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames(queueName);
        container.setMessageListener(pluginQueueListener);
        container.setPrefetchCount(5);
        container.setConcurrentConsumers(5);
        container.setMaxConcurrentConsumers(10);
        container.initialize();
        container.start();
        this.beanFactory.registerSingleton(queueName + routingKey, container);
        log.info("MQ队列初始化中>>>>>>>>RabbitMQ create new Queue '" + queueName + "' in '" + ExchangeTypes.DIRECT  + "' with '" + routingKey + "'");
    }
    

    /**
     * 卸载监听
     *
     * @param queueName 队列名称
     * @author leixiaohong
     */
    private void removeListener(String queueName, String routingKey) {
        SimpleMessageListenerContainer listenerContainer = beanFactory.getBean(queueName + routingKey, SimpleMessageListenerContainer.class);
        listenerContainer.shutdown();
        ////销毁bean
        this.beanFactory.destroySingleton(queueName + routingKey);

    }

    /**
     * 删除队列
     *
     * @param queueName 队列名称
     * @author leixiaohong
     */
    private void deleteQueue(String queueName) {
        QueueInformation queueInfo = rabbitAdmin.getQueueInfo(queueName);
        if (queueInfo != null) {
            rabbitAdmin.deleteQueue(queueName);
        }
    }

    /**
     * 删除交换机
     *
     * @param exchangeName 交换机
     * @author leixiaohong
     */
    private void deleteExchange(String exchangeName) {
        rabbitAdmin.deleteQueue(exchangeName);
    }


}
  • MQ的监听类
java 复制代码
import cn.hutool.core.convert.Convert;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.stereotype.Component;
import webber.aiservice.processer.engine.plugin.bus.ProcessBus;
import webber.aiservice.processer.engine.plugin.manager.ProcessManagerHelper;
import webber.aiservice.processer.plugin.PluginDesc;
import webber.aiservice.processer.plugin.SourceContent;
import webber.aiservice.processer.plugin.util.JacksonUtil;

import java.nio.charset.StandardCharsets;

/**
 * 监听方法类
 **/
@Slf4j
@Component
public class PluginQueueListener implements MessageListener {
    @Override
    public void onMessage(Message message) {
        try {
            String msg = new String(message.getBody(), StandardCharsets.UTF_8);
            log.info("msg:{}",msg)
        } catch (Exception e) {
            log.error("mq处理异常:{}, 插件信息: {}", ExceptionUtils.getStackTrace(e), pluginId);
        }
    }


}
相关推荐
IT枫斗者枫哥3 小时前
MyBatis一对多分页:LIMIT 20,为什么凑不齐20个订单?
java·数据库
代码方舟3 小时前
Java数据工程:利用天远全网运营商三要素优化线上实名认证合规体验
java·人工智能
BBmmo3 小时前
我的 Java 学习笔记 · 第 7 篇:泛型与通配符
java
独泪了无痕3 小时前
Hutool之RandomUtil:随机数生成的终极利器
java·后端
花开路口3 小时前
深入理解 Java/Kotlin 协变与逆变
java·kotlin
运行时异常3 小时前
【WMS 仓储系统集成 AI Agent 实战】第 7 讲:Vue3 前端工程化——Token 刷新锁、Markdown 渲染踩坑与权限体系
java
她的男孩3 小时前
开放接口限流从 20 改到 200 还是每分钟 20 次:拆完防重放+幂等+限流,我找到 5 个静默失效的坑
java·后端·架构
天天被压力3 小时前
【Python 量化取数指南 #13】Python 把行情落库:sqlite 一键存,回测随用随取
java·人工智能·python
天天被压力3 小时前
【Python 量化取数指南 #14】Python 清洗行情数据:复权停牌对齐,回测不翻车
java·人工智能·python
独泪了无痕3 小时前
开发利器Hutool之MapUtil的使用
java·后端