能否修改/删除ServiceBusReceivedMessage应用属性?需重置重试计数器
解决方案
由于ServiceBusReceivedMessage的ApplicationProperties是只读属性,无法直接修改原消息的属性,要实现死信消息不带retryCounter或重置其值为0,你需要通过创建新消息并手动发送到死信队列的方式来实现,具体步骤如下:
- 在达到最大重试次数时,创建一个新的
ServiceBusMessage实例,复制原消息的所有内容 - 移除新消息中的
RetryCount属性(或重置为0) - 手动将新消息发送到死信队列,并添加标准死信属性(如死信原因、错误描述)
- 标记原消息为完成,避免重复处理
修改后的代码示例
catch (Exception ex) when (ex.Message.Contains("Not Found")) { int retries = 0; var parsedMessage = _messageReceiver.ParseServiceBusMessage(message); // create new sb message and retrieve retry count var newMessage = new ServiceBusMessage(message); newMessage.ApplicationProperties.TryGetValue("RetryCount", out object retry); if (retry != null) retries = Convert.ToInt32(retry); // retry less than max count - increment count, submit new msg to service bus, complete previous sb message if (retries < _config.MaxRetryCount) { var msgSuffix = DateTime.Now.ToString("yyyy-MM-dd H:mm:ss.FFFFFF"); newMessage.MessageId = $"{parsedMessage.Transaction} {msgSuffix}"; if (!newMessage.ApplicationProperties.ContainsKey("RetryCount")) newMessage.ApplicationProperties.Add("RetryCount", (retries + 1).ToString()); else { newMessage.ApplicationProperties.Remove("RetryCount"); newMessage.ApplicationProperties.Add("RetryCount", (retries + 1).ToString()); } newMessage.ScheduledEnqueueTime = DateTime.UtcNow.AddSeconds(_config.HoldServiceBusMsgMinutes); await outputEvents.AddAsync(newMessage); log.LogInformation("Transaction not found. Resubmitted to service bus {transaction}", parsedMessage.Transaction); await _messageReceiver.CompleteMessageAsync(message, messageReceiver); } // max retries reached - 处理死信消息,移除/重置RetryCount else { log.LogError("Transaction number {transaction} has reached max number of 404 retries", parsedMessage.Transaction); // 1. 创建新消息,复制原消息内容 var deadLetterMsg = new ServiceBusMessage(message); // 2. 移除RetryCount属性,如需重置为0则替换为Add操作 if (deadLetterMsg.ApplicationProperties.ContainsKey("RetryCount")) { deadLetterMsg.ApplicationProperties.Remove("RetryCount"); // 若要重置为0,取消下面注释 // deadLetterMsg.ApplicationProperties.Add("RetryCount", 0); } // 3. 添加标准死信属性,和系统自动死信格式对齐 deadLetterMsg.ApplicationProperties.Add("DeadLetterReason", "Max retry count reached"); deadLetterMsg.ApplicationProperties.Add("DeadLetterErrorDescription", ex.Message); // 4. 获取死信队列路径(根据你的实际队列/主题订阅调整) // 队列的死信路径:$"{队列名称}/$DeadLetterQueue" // 主题订阅的死信路径:$"{主题名称}/subscriptions/{订阅名称}/$DeadLetterQueue" var deadLetterQueuePath = $"{_config.QueueName}/$DeadLetterQueue"; using var deadLetterSender = _serviceBusClient.CreateSender(deadLetterQueuePath); // 发送到死信队列 await deadLetterSender.SendMessageAsync(deadLetterMsg); // 5. 完成原消息,避免重复处理 await _messageReceiver.CompleteMessageAsync(message, messageReceiver); } }
注意事项
- 确保已在依赖注入中正确配置
ServiceBusClient实例 - 根据你使用的是队列还是主题订阅,调整死信队列的路径格式
- 手动发送的死信消息会保留原消息的核心内容,同时移除/重置了
RetryCount属性,且添加了符合规范的死信元数据
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

