介绍
RabbitMQ基于AMQP协议,开源,实现服务间的异步消息通讯和服务间的解耦。
4种工作模式:
Work模式
订阅/发布模式
路由模式
主题模式(通配符模式)
Work模式:用于抢红包、秒杀等应用场景。一个队列,多个消费者,但一条消息只会由一个消费者消费。这种模式又分轮询分发和公平分发。轮询分发就是消息依次平均的发送给每个消费者,公平分发就是消息按照消费者空闲程度分配任务。
订阅/发布模式:用于群发消息等应用场景。消息发送到交换机,由交换机发送到队列,订阅了队列的消费者获取消息。
路由模式:和订阅/发布模式相同,但增加了路由功能,不同关键字的消息发送到不同的队列。
主题模式:和路由模式相同,但增加了模糊匹配功能。
消息的可靠传输:
- 持久化
交换器、队列、消息都设置成持久化,这三者默认就是持久化的。
2. 生产者消息确认机制
ConfirmCallback:确认消息是否正确到达Exchange。
ReturnCallback:消息不能正确到达路由。
<rabbit:connection-factory host="localhost"
port="5672" username="admin" password="admin" id="rabbitConnectionFactory" virtual-host="testhost"
publisher-confirms="true" publisher-returns="true" cache-mode="CHANNEL" channel-cache-size="10"
thread-factory="tf" />
<rabbit:template id="fanoutTemplate" connection-factory="rabbitConnectionFactory" exchange="myExchange2" mandatory="true"
confirm-callback="msgSendConfirmCallback" return-callback="msgSendReturnCallback"></rabbit:template>
public class MsgSendConfirmCallback implements ConfirmCallback{
/* (non-Javadoc)
* @see org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback#confirm(org.springframework.amqp.rabbit.support.CorrelationData, boolean, java.lang.String)
*/
public void confirm(CorrelationData correlationData, boolean ack,
String cause) {
System.out.println("ack:" + ack + ",cause:" + cause);
if(ack){
System.out.println(correlationData);
System.out.println("消息发送成功");
}else{
System.out.println(correlationData);
System.out.println("消息发送失败" + cause);
}
}
}
public class MsgSendReturnCallback implements ReturnCallback{
/* (non-Javadoc)
* @see org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback#returnedMessage(org.springframework.amqp.core.Message, int, java.lang.String, java.lang.String, java.lang.String)
*/
public void returnedMessage(Message message, int replyCode,
String replyText, String exchange, String routingKey) {
// TODO Auto-generated method stub
String msg = new String(message.getBody());
System.out.println("replyCode:" + replyCode + ",replyText:" + replyText
+ ",exchange:" + exchange + ",routingKey:" + routingKey
+ ",message:" + msg);
}
}
3. 消费者消息确认机制
消息通过ACK确认是否被正确接收,每个消息都要被确认,可以手动ACK也可以自动ACK,如果不确认,消息会发送到下一个消费者。
<rabbit:listener-container connection-factory="rabbitConnectionFactory" acknowledge="manual" >
<rabbit:listener ref="foo" queue-names="ysjQueue" />
</rabbit:listener-container>
<bean id="foo" class="rabbitServer.Foo"></bean>
public class Foo implements ChannelAwareMessageListener{
/* (non-Javadoc)
* @see org.springframework.amqp.rabbit.core.ChannelAwareMessageListener#onMessage(org.springframework.amqp.core.Message, com.rabbitmq.client.Channel)
*/
public void onMessage(Message message, Channel channel) throws Exception {
// 停顿2秒,模拟消费慢的场景
Thread.sleep(1000);
//System.out.println(message.getMessageProperties().getCorrelationIdString());
System.out.println("Consumer1 Foo2:" + message.toString());
// 确认
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
// 不确认
///channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
}
}
4. 死信队列
Queue中的消息超时、消息被拒绝、队列满,消息挪到死信队列。
<!-- 定义队列 -->
<rabbit:queue auto-delete="false" exclusive="false" durable="true" name="ysjQueue" >
<rabbit:queue-arguments>
<!-- 设置消息存活时间 -->
<entry key="x-message-ttl">
<value type="java.lang.Long">30000</value>
</entry>
<!-- 指定死信交换机 -->
<entry key="x-dead-letter-exchange">
<value type="java.lang.String">alter</value>
</entry>
</rabbit:queue-arguments>
</rabbit:queue>
<rabbit:queue auto-delete="false" exclusive="false" durable="true" name="deadQueue" />
<rabbit:fanout-exchange name="alter" durable="true" auto-delete="false" >
<rabbit:bindings>
<rabbit:binding queue="deadQueue" ></rabbit:binding>
</rabbit:bindings>
</rabbit:fanout-exchange>