RabbitMQ相关知识
#介绍
RabbitMQ 是使用一种比较小众的编程语言:Erlang 语言编写的,它最早是为电信行业系统之间的可靠通信设计的,是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。
RabbitMQ 就像它的名字中的兔子一样:轻量级、迅捷,它的 Slogan,也就是宣传口号,也很明确地表明了 RabbitMQ 的特点:Messaging that just works,“开箱即用的消息队列”。也就是说,RabbitMQ 是一个相当轻量级的消息队列,非常容易部署和使用。
另外 RabbitMQ 还号称是世界上使用最广泛的开源消息队列,是不是真的使用率世界第一,我们没有办法统计,但至少是“最流行的消息中间之一”,这是没有问题的。
AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。
基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。Erlang中的实现有RabbitMQ等。
#SpringBoot集成RabbitMQ
pom配置
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
yml配置
spring:
rabbitmq:
host: localhost
username: guest
password: guest
port: 5672
配置类
@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 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"; public static final String ROUTING_KEY_A = "spring-boot-routingKey_A"; public static final String ROUTING_KEY_B = "spring-boot-routingKey_B"; public static final String ROUTING_KEY_C = "spring-boot-routingKey_C"; @Bean public CachingConnectionFactory connectionFactory() { CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host, port); connectionFactory.setUsername(username); connectionFactory.setPassword(password); connectionFactory.setVirtualHost("/"); connectionFactory.setPublisherConfirms(true); return connectionFactory; } /** * 必须是prototype类型 */ @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public RabbitTemplate rabbitTemplate() { return new RabbitTemplate(connectionFactory()); } /** * 针对消费者配置 * 1. 设置交换机类型 * 2. 将队列绑定到交换机 * FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念 * HeadersExchange :通过添加属性key-value匹配 * DirectExchange:按照routingkey分发到指定队列 * TopicExchange:多关键字匹配 */ @Bean public DirectExchange defaultExchange() { return new DirectExchange(EXCHANGE_A); } @Bean public Queue queueA() { //队列持久 return new Queue(QUEUE_A, true); } @Bean public Queue queueB() { //队列持久 return new Queue(QUEUE_B, true); } @Bean public Binding binding() { return BindingBuilder.bind(queueA()).to(defaultExchange()) .with(RabbitConfig.ROUTING_KEY_A); } @Bean public Binding bindingB(){ return BindingBuilder.bind(queueB()).to(defaultExchange()).with(RabbitConfig.ROUTING_KEY_B); } }
生产消息
@Slf4j @Component public class MsgProducer implements RabbitTemplate.ConfirmCallback { /** * 由于rabbitTemplate的scope属性设置为ConfigurableBeanFactory.SCOPE_PROTOTYPE,所以不能自动注入 */ private RabbitTemplate rabbitTemplate; /** * 构造方法注入rabbitTemplate */ @Autowired public MsgProducer(RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; //rabbitTemplate如果为单例的话,那回调就是最后设置的内容 rabbitTemplate.setConfirmCallback(this); } public void sendMsg(String content) { CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString()); //把消息放入ROUTING_KEY_A对应的队列当中去,对应的是队列A rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_A, RabbitConfig.ROUTING_KEY_A, content, correlationId); } @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { log.info(" 回调id:{}", correlationData); if (ack) { log.info("消息成功消费"); } else { log.info("消息消费失败:{}", cause); } } }
消费者一
@Slf4j
@Component
@RabbitListener(queues = RabbitConfig.QUEUE_A)
public class MsgReceiverOne {
@RabbitHandler
public void process(String message) {
log.info("处理器one接收处理队列A当中的消息:{}", message);
}
}
消费者二
@Slf4j @Component @RabbitListener(queues = RabbitConfig.QUEUE_A) public class MsgReceiverTwo { @RabbitHandler public void process(String message) { log.info("处理器two接收处理队列A当中的消息:{}", message); } }
测试
@RunWith(SpringRunner.class) @SpringBootTest public class RabbitMqTestCase { @Autowired private MsgProducer msgProducer; @Test public void contextLoads() { for (int i = 0; i < 10; i++) { msgProducer.sendMsg("这是一条测试消息,来自RabbitMQ"); } } }