rabbitmq中的 router key
对于消息发布者而言它只负责把消息发布出去,甚至它也不知道消息是发到哪个queue,消息通过exchange到达queue,exchange的职责非常简单,就是一边接收发布者的消息一边把这些消息推到queue中。
而exchange是怎么知道消息应该推到哪个queue呢,这就要通过绑定queue与exchange时的routingkey了,通过代码进行绑定并且指定routingkey,下面有一张关系图,p(发布者) —> x(exchange) bindding(绑定关系也就是我们的routingkey) 红色代表着queue
在消息的生产者端:
@Component public class RabbitOrderSender { //自动注入RabbitTemplate模板类 @Autowired private RabbitTemplate rabbitTemplate; @Autowired private BrokerMessageLogMapper brokerMessageLogMapper; //回调函数: confirm确认 final RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() { @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { System.err.println("correlationData: " + correlationData); String messageId = correlationData.getId(); if(ack){ //如果confirm返回成功 则进行更新 brokerMessageLogMapper.changeBrokerMessageLogStatus(messageId, Constants.ORDER_SEND_SUCCESS, new Date()); } else { //失败则进行具体的后续操作:重试 或者补偿等手段 System.err.println("异常处理..."); } } }; //发送消息方法调用: 构建自定义对象消息 public void sendOrder(Order order) throws Exception { // 通过实现 ConfirmCallback 接口,消息发送到 Broker 后触发回调,确认消息是否到达 Broker 服务器,也就是只确认是否正确到达 Exchange 中 rabbitTemplate.setConfirmCallback(confirmCallback); //消息唯一ID CorrelationData correlationData = new CorrelationData(order.getMessageId()); rabbitTemplate.convertAndSend("order-exchange", "order.ABC", order, correlationData); } }
利用rabbitTemplate(import org.springframework.amqp.rabbit.core.RabbitTemplate;需要在pom.xml中导入amqp的依赖)的convertAndSend方法就可以发送,这里order-exchange为交换机exchange,order.ABC为routingKey,并没有指定对应消息需要发往哪个队列,还有指定消息回调。
在消息的消费者端:
@Component public class OrderReceiver { //配置监听的哪一个队列,同时在没有queue和exchange的情况下会去创建并建立绑定关系 @RabbitListener(bindings = @QueueBinding( value = @Queue(value = "order-queue",durable = "true"), exchange = @Exchange(name="order-exchange",durable = "true",type = "topic"), key = "order.*" ) ) @RabbitHandler//如果有消息过来,在消费的时候调用这个方法 public void onOrderMessage(@Payload Order order, @Headers Map<String,Object> headers, Channel channel) throws IOException { //消费者操作 System.out.println("---------收到消息,开始消费---------"); System.out.println("订单ID:"+order.getId()); /** * Delivery Tag 用来标识信道中投递的消息。RabbitMQ 推送消息给 Consumer 时,会附带一个 Delivery Tag, * 以便 Consumer 可以在消息确认时告诉 RabbitMQ 到底是哪条消息被确认了。 * RabbitMQ 保证在每个信道中,每条消息的 Delivery Tag 从 1 开始递增。 */ Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG); /** * multiple 取值为 false 时,表示通知 RabbitMQ 当前消息被确认 * 如果为 true,则额外将比第一个参数指定的 delivery tag 小的消息一并确认 */ boolean multiple = false; //ACK,确认一条消息已经被消费。不然的话,在rabbitmq首页会有Unacked显示为未处理数1. channel.basicAck(deliveryTag,multiple); } }
消费者需要指定监听的队列,routingkey,和exchage,如果在localhost:15672的rabbitmq的首页没有手动创建,@RabbitListener会自动帮我们创建的并绑定关系。rabbitmq的routingkey还可以用来过滤从队列中取的的信息。