Nếu nhắn w vì không được công nhận và ứng dụng không thành công, nó sẽ được phân phối lại tự động và redelivered
thuộc tính trên phong bì sẽ được đặt thành true
(trừ khi bạn tiêu thụ chúng với cờ no-ack = true
).
UPD:
Bạn phải nack
nhắn với trả tàu cờ trong khối catch của bạn
try {
//Do some business logic
} catch (Exception $ex) {
//Log exception
return $queue->nack($msg->getDeliveryTag(), AMQP_REQUEUE);
}
Hãy coi chừng các thông điệp vô cùng nacked trong khi đếm trả tàu không thực hiện trong RabbitMQ và trong giao thức AMQP ở tất cả.
Nếu bạn không muốn gây rối với những thông điệp đó và chỉ đơn giản là muốn thêm một số chậm trễ bạn có thể muốn thêm một số sleep()
hoặc usleep()
trước nack
gọi phương thức, nhưng nó không phải là một ý tưởng tốt ở tất cả.
Có nhiều kỹ thuật để đối phó với vấn đề chu kỳ Phân phối lại:
1. Dựa vào Dead Letter Exchanges
- ưu: đáng tin cậy, tiêu chuẩn, rõ ràng
- khuyết điểm: yêu cầu logic thêm
2.Sử dụng per message or per queue TTL
- ưu: dễ thực hiện, cũng chuẩn, rõ ràng
- nhược điểm: với hàng đợi lâu bạn có thể mất một số điệp
Ví dụ (lưu ý, rằng cho hàng đợi ttl chúng tôi vượt qua chỉ số và cho ttl nhắn - bất cứ điều gì mà sẽ là chuỗi số):
2,1 mỗi ttl nhắn:
$queue = new AMQPQueue($channel);
$queue->setName('my-queue');
$queue->declareQueue();
$queue->bind('my-exchange');
$exchange->publish(
'message at ' . microtime(true),
null,
AMQP_NOPARAM,
array(
'expiration' => '1000'
)
);
2.2. Mỗi hàng đợi ttl:
$queue = new AMQPQueue($channel);
$queue->setName('my-queue');
$queue->setArgument('x-message-ttl', 1000);
$queue->declareQueue();
$queue->bind('my-exchange');
$exchange->publish('message at ' . microtime(true));
3. Giữ redelivers đếm hoặc trái số redelivers (aka hop hạn chế hoặc ttl trong ngăn xếp IP) trong nội dung thư hoặc tiêu đề
- ưu: cung cấp cho bạn kiểm soát thêm trên tin nhắn trọn đời trên cấp ứng dụng
- điểm: chi phí đáng kể trong khi bạn phải sửa đổi thư và xuất bản lại, ứng dụng cụ thể, không rõ ràng
Code:
$queue = new AMQPQueue($channel);
$queue->setName('my-queue');
$queue->declareQueue();
$queue->bind('my-exchange');
$exchange->publish(
'message at ' . microtime(true),
null,
AMQP_NOPARAM,
array(
'headers' => array(
'ttl' => 100
)
)
);
$queue->consume(
function (AMQPEnvelope $msg, AMQPQueue $queue) use ($exchange) {
$headers = $msg->getHeaders();
echo $msg->isRedelivery() ? 'redelivered' : 'origin', ' ';
echo $msg->getDeliveryTag(), ' ';
echo isset($headers['ttl']) ? $headers['ttl'] : 'no ttl' , ' ';
echo $msg->getBody(), PHP_EOL;
try {
//Do some business logic
throw new Exception('business logic failed');
} catch (Exception $ex) {
//Log exception
if (isset($headers['ttl'])) {
// with ttl logic
if ($headers['ttl'] > 0) {
$headers['ttl']--;
$exchange->publish($msg->getBody(), $msg->getRoutingKey(), AMQP_NOPARAM, array('headers' => $headers));
}
return $queue->ack($msg->getDeliveryTag());
} else {
// without ttl logic
return $queue->nack($msg->getDeliveryTag(), AMQP_REQUEUE); // or drop it without requeue
}
}
return $queue->ack($msg->getDeliveryTag());
}
);
Có thể có một số cách khác để kiểm soát tốt hơn thông điệp redelivers dòng chảy.
Kết luận: không có giải pháp viên đạn bạc. Bạn phải quyết định giải pháp nào phù hợp với nhu cầu của bạn tốt nhất hoặc tìm ra thứ gì đó khác, nhưng đừng quên chia sẻ nó ở đây;)
Bạn sử dụng ngôn ngữ nào và bạn có thể cung cấp một số mã không? – pinepain
@ zaq178miami, xem tin nhắn đã chỉnh sửa của tôi –
@Bram_Gerritsen, xem cập nhật câu trả lời của tôi – pinepain