fix: Worker 进程独立 Channel + 进程内指数退避重试
- 每个 Worker 消费者使用独立 AMQP Channel,互不影响 - 用 runWorkerWithRetry 包装每个 Worker,断开自动重连 - 用进程内指数退避重试替代失效的 Nack+DLX 重试机制 - 拓扑声明改用临时 Channel,声明完即关闭
This commit is contained in:
@@ -66,18 +66,28 @@ func (w *NotificationWorker) Run(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (w *NotificationWorker) handleDelivery(ctx context.Context, d amqp.Delivery) {
|
||||
retryCount := rabbitmq.GetRetryCount(d)
|
||||
if err := w.process(ctx, d); err != nil {
|
||||
if retryCount >= rabbitmq.MaxRetryCount {
|
||||
log.Printf("notification worker: max retries, dropping: %v", err)
|
||||
_ = d.Ack(false)
|
||||
const maxRetries = 3
|
||||
for i := 0; i <= maxRetries; i++ {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
_ = d.Nack(false, true)
|
||||
return
|
||||
default:
|
||||
}
|
||||
log.Printf("notification worker: failed (retry %d/%d): %v", retryCount+1, rabbitmq.MaxRetryCount, err)
|
||||
_ = d.Nack(false, true)
|
||||
if err := w.process(ctx, d); err != nil {
|
||||
if i >= maxRetries {
|
||||
log.Printf("notification worker: 重试 %d 次后仍失败, 丢弃: %v", maxRetries, err)
|
||||
_ = d.Ack(false)
|
||||
return
|
||||
}
|
||||
wait := time.Duration(1<<uint(i)) * time.Second
|
||||
log.Printf("notification worker: 处理失败, %v 后重试 (%d/%d): %v", wait, i+1, maxRetries, err)
|
||||
time.Sleep(wait)
|
||||
continue
|
||||
}
|
||||
_ = d.Ack(false)
|
||||
return
|
||||
}
|
||||
_ = d.Ack(false)
|
||||
}
|
||||
|
||||
func (w *NotificationWorker) process(ctx context.Context, d amqp.Delivery) error {
|
||||
|
||||
Reference in New Issue
Block a user