QueueingConsumer过时
QueueingConsumer在Rabbitmq客户端3.x版本中用的如火如荼,但是在4.x版本开初就被标记为@Deprecated。
Consumer的消费模式有Pull 和 Push两种,而经常用到的就是Push模式,Push模式在3.x的用法demo如下:
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicQos(1);
channel.basicConsume(QUEUE_NAME, false, "consumer_zzh",consumer);
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [X] Received '" + message + "'");
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
break;
}
在官方文档中推荐使用继承DefaultConsumer的方式:
boolean autoAck = false;
channel.basicConsume(queueName, autoAck, "myConsumerTag",
new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body)
throws IOException
{
String routingKey = envelope.getRoutingKey();
String contentType = properties.getContentType();
long deliveryTag = envelope.getDeliveryTag();
// (process the message components here ...)
channel.basicAck(deliveryTag, false);
}
});
QueueingConsumer内部其实是一个LinkBlockingQueue,它将从broker端接受到的信息先暂存到这个LinkBlockingQueue中,然后消费端程序在从这个LinkBlockingQueue中take出消息。试下一下,如果我们不take消息或者说take的非常慢,那么LinkBlockingQueue中的消息就会越来越多,最终造成内存溢出。
这个问题可以通过设置Basic.Qos来很好的解决。
DefaultConsumer还有一下方法:
- handleShutdownSignal方法 当Channel与Conenction关闭的时候会调用,
- handleCancelOk方法会在其它方法之前调用,返回消费者标签
handleCancelOk与handleCancel消费者可以显式或者隐式的取水订单的时候调用,也可以通过channel.basicCancel方法来显式的取消一个消费者订阅
首先触发handleConsumeOk方法,之后触发handleDelivery方法,最后才触发handleCancelOk方法
@Override
public void handleConsumeOk(String consumerTag) {
this._consumerTag = consumerTag;
}
@Override
public void handleCancelOk(String consumerTag) {
// no work to do
}
@Override
public void handleCancel(String consumerTag) throws IOException {
// no work to do
}
@Override
public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) {
// no work to do
}
@Override
public void handleRecoverOk(String consumerTag) {
// no work to do
}
进入basicConsume方法内部看一看,他有三个实现但最终都是ChannerlN.class下的 public String basicConsume(String queue, final boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map<String, Object> arguments, final Consumer callback) throws IOException {}方法(下面代码块中的源码1)在最终执行,我们可以看到其只调用了Consumer的HandleConsumeOk方法,其方法实现如源码2;
//自己的consumer
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String