-
需求: 需求中会有插件的动态安装和卸载,需求需要安装一个插件动态的创建(初始化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);
}
}
}