赞
踩
ack
分为自动ack和手动ack两种
如果是自动ack,有两个弊端:
qos控制
,可能消费者客户端因为瞬间收到太多消息导致服务挂掉所以,常用的是手动ack
应答
一般手动ack
处理业务的逻辑如下:
try {
//do logic
if(success) {
//手动ack应答
$msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
}
} catch (Exception $e) {
echo "wrong";
//log
}
咋一看是没问题,但如果上面logic
中的callback
有Bug的话,就会导致所有的消息都抛出异常,然后队列的Unacked消息数
暴涨,导致MQ响应越来越慢,然后down掉
原因:因为上面callback抛出异常,所以MQ没有得到ack响应,注意:这些消息会堆积在Unacked消息里,不会抛弃,即使另外打开一个消费者也不会被消费,直到原来的消费者客户端断开重连时,才会变成ready,这时如果通过qos
设置了prefetch
,没有ack响应的话,Broker不会再分配新的消息下来,就导致了阻塞
nack
是什么呢?其实就是会通知MQ把消息塞回的队列头部(不是尾部),而不是变成Unacked,这样消费者客户端可以直接获取到这条消息。
但是问题又来了,如果上面callback有问题,那就算放回队首了,下次取出消费,还是会报错,又被送回队首,这样就陷入死循环了
解决上面出现的问题的最好的办法就是:
try {
//do logic
} catch (Exception $e) {
Log.Info($msg)
} finally {
//最终怎样都手动ack应答
$msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
}
也就是不管是否出现异常,都要ack,区别在与出现异常时先把消息数据catch到一个记录表里,然后ack,最后再另外统一处理这些消费失败的消息
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。