概述:
JMS
JMS中有两个典型的消费概念。
Queue,P2P消费,queue中的每个消息以roundrobin的方式,分发给所有已订阅该queue的consumer,只有一个consumer能收到并处理此消息。
Topic,publish-subscribe,queue中的每个消息以broadcast的方式,分发给所有已订阅该queue的consumer,每个consumer都会收到并处理此消息。
AMQP
比起JMS,AMQP更复杂一点,定义了Exchange和Binding机制。
Exchange分为Direct(全匹配定向路由), Fanout(发布-订阅,广播路由), Topic(基于正则进行路由), Header,共4种类型。
Producer发布消息时,只和Exchange打交道,所以Exchange必须事先定义。
Consumer接收消息时,只和Queue打交道。
Queue可以和Exchange进行Binding,在什么时候进行绑定呢?记住一个AMQP协议中的默认规则,即Producer发布消息时,只和Exchange打交道。
MQTT
更轻量级的消息队列,多用于移动领域。
RabbitMQ中的一些事项
1,要持久化消息,Queue必须声明为durable=true,Message必须声明为PERSISTENT_TEXT_PLAIN这样的持久化。
2,Queue中的消息只能被一个Consumer接收并成功消费。
3,Consumer消费消息时,推荐设置autoAck=false。consumerChannel.basicConsume(queueName, false, consumer);//autoAck is false
4,Channel的prefetchCount推荐设置为1,Server每次向Consumer只推送一条消息。consumerChannel.basicQos(1);
默认是以轮训的方式消息Queue,但设置prefetchCount设置为1后,就是能者多干,弱者少干。
举例来说,默认的消费方式是这样的,假设queue中有3条消息。
consumer1处理慢,先处理msg1,一直是处理中。
consumer2处理快,处理msg2,很快处理完,但是,consumer2必须等待,因为consumer1还有没处理完。
consumer1处理完msg1,consumer1继续收到并处理消息msg3
consumer2接收并处理msg4。
这种方式收roundrobin,就是非常公平的分发消息。
如果prefetchCount设置为1,consumer接收消息的方式就有所改变了。
consumer1接收并处理msg1,处理中。。。
consumer2接收并正理msg2,很快处理完了。
consumer2再继续接收msg3,很快处理完了。
consumer2再继续处理msg4,很快处理完了。
consumer1现在才处理完msg1,好慢啊。
consumer1再继续处理msg5,处理中。。。
看出来了吧,这种方式,就是谁处理的快,谁就多干。
使用注意事项
channel.BasicQos(0, 1, false),实现公平调度的方式就是让每个消费者在同一时刻会分配一个任务,设置mq每次向consumer推送1条消息,用以保证consumer的消费能力,不会有大量unack消息在queue中。
channel.basicAck(false)和channel.basicReject()都会将消息回退到queue队列头,再次推送到consumer,导致有问题的消息始终一直尝试被消息,所以可以尝试ack=ture,再publish一次,这样该消息被push到queue队列尾。
可以尝试多次业务上去消费message,如果还是不能正常消费消息,自己记录一下Log吧。
推荐自己手动ack。
queue和exchange建议必须持久化
多个consumer要以共享一个connection,但必须使用不同的channel。
mq集群不能kill -9,建议用kill -15。