Hola, soy Chenxi. Me alegra que puedas leerlo. Este artículo sigue compartiendo los casos prácticos de las colas de mensajes, compartiéndolos con principiantes y progresando juntos.
Directorio de artículos
1. Prefacio
La intención original de organizar algunos artículos en cola de mensajes es que muchos casos en Internet están muy fragmentados cuando aprendes, y el código también. Para facilitar el aprendizaje de los principiantes, organizaremos un caso completo. El código es completamente real y utilizable. ¡Practica tú mismo!
cola de mensajes
Por primera vez que aprendamos sobre la cola de mensajes, debemos comprender sus escenarios de aplicación, ¿por qué usarlo? ¿Y cómo usarlo? Organice este artículo para compartirlo con principiantes y proporcione un caso detallado, ¡el siguiente código se puede practicar directamente!
Los tres puntos centrales de la cola de mensajes: desacoplamiento, asíncrono y recorte de picos.
Artículo de referencia: explicación detallada de la función de cola de mensajes (desacoplamiento, asíncrono, recorte de picos)
La cola de mensajes también está diseñada para el productor, el principio del consumidor se puede entender simplemente
Artículo de referencia: Código detallado del problema del consumidor productor (Java multiproceso)
En segundo lugar, los detalles del código
Código relacionado con el productor
/**
* 编写消息的生产者
*/
@Component
public class MsgProducer implements RabbitTemplate.ConfirmCallback {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
//由于rabbitTemplate的scope属性设置为ConfigurableBeanFactory.SCOPE_PROTOTYPE,所以不能自动注入
private RabbitTemplate rabbitTemplate;
/**
* 构造方法注入rabbitTemplate
*/
@Autowired
public MsgProducer(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
rabbitTemplate.setConfirmCallback(this); //rabbitTemplate如果为单例的话,那回调就是最后设置的内容
}
/**
* 发送消息方法一个交换机配一个路由配一个队列
* @param content
*/
public void sendMsg(String content) {
CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
//把消息放入ROUTINGKEY_A对应的队列当中去,对应的是队列A
rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_A, RabbitConfig.ROUTINGKEY_A, content, correlationId);
rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_B, RabbitConfig.ROUTINGKEY_B, content, correlationId);
}
/**
* 广播模式
* @param content
*/
public void sendAll(String content) {
rabbitTemplate.convertAndSend("fanoutExchange","", content);
}
/**
* 回调
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
//logger.info(" 回调id:" + correlationData);
if (ack) {
logger.info("消息成功消费");
} else {
logger.info("消息消费失败:" + cause);
}
}
}
Código relacionado sobre la capa del controlador
@RestController
public class SendController {
@Autowired
private MsgProducer msgProducer;
@RequestMapping(value = "/send",method = RequestMethod.GET)
public void send(int length){
for (int i=1;i<=length;i++){
msgProducer.sendMsg("这是我发送的第"+i+"个信息");
}
}
@RequestMapping(value = "/sendAll",method = RequestMethod.GET)
public void sendAll(int length){
for (int i=1;i<=length;i++){
msgProducer.sendAll("这是我发送的第"+i+"个信息");
}
}
}
Código de consumidor
@Component
@RabbitListener(queues = RabbitConfig.QUEUE_A)
public class MsgReceiver_one {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@RabbitHandler
public void process(String content) {
logger.info("消费者one接收处理队列A当中的消息: " + content);
}
}
Estos dos escuchan la cola A y la cola B respectivamente
@Component
@RabbitListener(queues = RabbitConfig.QUEUE_B)
public class MsgReceiver_two {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@RabbitHandler
public void process(String content) {
logger.info("消费者two接收处理队列A当中的消息: " + content);
}
}
Prueba: ingrese la primera ruta de acceso en el navegador e ingrese los parámetros relevantes
La primera ruta aquí es que el productor envía a las colas A y B respectivamente
Consulte la información relacionada con la impresión de la consola
Prueba: ingrese la segunda ruta e ingrese los parámetros relacionados en el navegador
La segunda ruta aquí es publicar en forma de transmisión, puede consumir y
ver la información relacionada con la impresión de la consola
http: // localhost: 15672 / # / queues
Información sobre el archivo de configuración del proyecto
@Configuration
public class RabbitConfig {
@Value("${spring.rabbitmq.host}")
private String host;
@Value("${spring.rabbitmq.port}")
private int port;
@Value("${spring.rabbitmq.username}")
private String username;
@Value("${spring.rabbitmq.password}")
private String password;
public static final String FANOUT_EXCHANGE="fanoutExchange";
//交换机
public static final String EXCHANGE_A = "my-mq-exchange_A";
public static final String EXCHANGE_B = "my-mq-exchange_B";
public static final String EXCHANGE_C = "my-mq-exchange_C";
//队列
public static final String QUEUE_A = "QUEUE_A";
public static final String QUEUE_B = "QUEUE_B";
public static final String QUEUE_C = "QUEUE_C";
//路由关键字 key
public static final String ROUTINGKEY_A = "spring-boot-routingKey_A";
public static final String ROUTINGKEY_B = "spring-boot-routingKey_B";
public static final String ROUTINGKEY_C = "spring-boot-routingKey_C";
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host,port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
//connectionFactory.setVirtualHost("/test");
connectionFactory.setPublisherConfirms(true);
return connectionFactory;
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
//必须是prototype类型
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
return template;
}
/**
* 针对消费者配置
* 1. 设置交换机类型
* 2. 将队列绑定到交换机
FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念
HeadersExchange :通过添加属性key-value匹配
DirectExchange:按照routingkey分发到指定队列
TopicExchange:多关键字匹配
*/
@Bean
public DirectExchange defaultExchangeA() {
return new DirectExchange(EXCHANGE_A);
}
@Bean
public DirectExchange defaultExchangeB() {
return new DirectExchange(EXCHANGE_B);
}
@Bean
public DirectExchange directExchangeC(){
return new DirectExchange(EXCHANGE_C);
}
/**
* 获取队列A
* @return
*/
@Bean
public Queue queueA() {
return new Queue(QUEUE_A, true); //队列持久
}
@Bean
public Queue queueB() {
return new Queue(QUEUE_B, true); //队列持久
}
@Bean
public Queue queueC() {
return new Queue(QUEUE_C, true); //队列持久
}
/**
* 队列绑定交换机
* @return
*/
@Bean
public Binding bindingA() {
return BindingBuilder.bind(queueA()).to(defaultExchangeA()).with(RabbitConfig.ROUTINGKEY_A);
}
@Bean
public Binding bindingB(){
return BindingBuilder.bind(queueB()).to(defaultExchangeB()).with(RabbitConfig.ROUTINGKEY_B);
}
@Bean
public Binding bindingC(){
return BindingBuilder.bind(queueC()).to(directExchangeC()).with(RabbitConfig.ROUTINGKEY_C);
}
//配置fanout_exchange
//fanout只能支持统一广播
@Bean
FanoutExchange fanoutExchange() {
return new FanoutExchange(RabbitConfig.FANOUT_EXCHANGE);
}
//把所有的队列都绑定到这个交换机上去
@Bean
Binding bindingExchangeA(FanoutExchange fanoutExchange) {
return BindingBuilder.bind(queueA()).to(fanoutExchange);
}
@Bean
Binding bindingExchangeB(FanoutExchange fanoutExchange) {
return BindingBuilder.bind(queueB()).to(fanoutExchange);
}
@Bean
Binding bindingExchangeC(FanoutExchange fanoutExchange) {
return BindingBuilder.bind(queueC()).to(fanoutExchange);
}
}
resumen:
1. Primero cree una clase de configuración y luego cree una cola
2. Cree el objeto que el productor usa en la cola de mensajes y luego entregue el mensaje que desea entregar.
3. Cree la capa de control, complete la ruta, cree el objeto productor y luego envíe el mensaje
4. Consumidores, completar el nombre de la cola de consumo, monitorear y prepararse para iniciar el consumo
The best investment is to invest in yourself.
2020.10.07 ¡Espero que te apresures a estar en tu amor!