介绍
RabbitMQ是消息代理。它接收信息和转发信息。你可以把他考虑成一个邮局。当你讲邮寄的信放在邮局时,你可以确定邮差先生或者女士会把邮件最终送到你的收件人手中。当然邮局和RabbitMQ最大的区别,RabbitMq不接受纸张,它只接收,存储,转发二进制的数据消息快。
下面讲一些RabbitMQ中的术语:
-
Producer
生成只不过意味着发送信息。发送信息的程序是生产者
-
Queue
队列是驻留在RabbitMQ内的邮箱的名称。尽管消息flow RabbitMQ和你的程序,但是他们只能存储在队列中。一个队列只受主机的内存和磁盘限制,它的本质是一个大的消息缓冲区。许多消费者可以将消息发送到一个队列,许多消费者可以尝试从一个队列接收数据,这就我们表示队列的方式。
-
Consumer
消费和接收有相同的意义。消费者是一个主要接收消息的程序
注意:生产者、消费者和代理不必都在同一主机上;实际上,在大多数应用程序中,它们并没有这样做。应用程序既可以是生成者也可以是消费者。
简单队列
简单队列,就是发送单个消息的消费者和接收信息并将其打印出来的使用者(消费者),不多叙述。
工作队列
工作队列主要是避免短时间内执行密集任务,并且必须等待它完成。我们将任务放在消息队列中,启动多个消费者,任务在他们中是共享的。
设计到工作队列,当然会有不同方式的工作队列
ack
关于ack这边多讲一点,message acknowledgment是消息确认,设置autoack=true之后,consumer返回一个ack(nowledgement),告诉rabbitMQ已经接受信息,处理了特定的消息,RabbitMQ可以自由地删除它。
轮询队列(Round-robin dispatching)
将autoAck设置为true,默认情况下,RabbitMQ会发送每条信息给另一个消费者。每个消费者都会获取相同数量的。并且是间隔形式的。如有c1,c2消费者,10条消息,c1是0,2,4,6,8,c2是1,3,5,7,9。当然,在我打断点时,发现对应的数据会都一次性发送到c1,和c2,c1和c2处理信息时,并不影响彼此。
公平队列
在RabbitMQ分发信息的时候,可能会发现,一个consumer很忙,另一个一点也不忙。因为RabbitMQ对此一无所知,只是将第N条信息,发送给第Nconsumer.
为了解决这个,我们将basicQos方法和prefetechCount=1设置一起用。换句话说,在处理并确认上一条信息之前,不要将新信息发送给工人。
int prefetchCount = 1;
channel.basicQos(prefetchCount);
并且,我们需要将autoAck设为false和处理完一条消息后发送ack给RabbitMQ
DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String msg = new String(body, "utf-8");
System.out.println("receive1 : " + msg);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
channel.basicAck(envelope.getDeliveryTag(),false);
}
}
};
boolean autoack = false;
channel.basicConsume(QUEUE_NAME,autoack,defaultConsumer);