【问题标题】:So many Service Bus Transient Errors?这么多服务总线瞬态错误?
【发布时间】:2017-10-18 22:55:33
【问题描述】:

我们有两个 Windows 服务,它们位于企业内部服务器上,并不断向云中的 Azure 服务总线发送消息。尽管消息最终确实会在服务总线上结束,但有时消息似乎在很长一段时间内都无法通过。

这给我们带来了延迟问题,因为我们依赖于消息到达服务总线并在一分钟内得到处理。但是,如下所示,一条消息可能会被“阻止”长达 30-40 分钟,然后才能进入 Azure 服务总线。这种情况每天都会发生,而且几乎在每个小时的某个时间都会发生。

错误主要是以下之一(本文末尾的示例日志):

  • 连接尝试失败,因为连接的一方在一段时间后没有正确响应,或者建立连接失败,因为连接的主机没有响应 191.239.XX.XXX:443

  • 与服务总线通信时出错。检查连接信息,然后重试。

  • 没有这样的主机已知

  • 请求操作未在分配的超时时间 00:01:10 内完成。分配给此操作的时间可能是较长超时的一部分。 TrackingId:f2db6377-e17d-401a-b339-11fbb51c7bf7,时间戳:19/05/2017 12:47:36 AM

我们向服务总线发送消息的方式如下,简化如下:

private TopicClient _azureTopic;

...
<Begin Loop>

if (_azureTopic == null)
{
   var connectionString = "Endpoint=sb://mynamespace.servicebus.windows.net/;SharedAccessKeyName=managerfiddev;SharedAccessKey=AABBCCDDEEFFGGHHHASDFADFAadfadfdfz=EntityPath=mytopic";
   _azureTopic = TopicClient.CreateFromConnectionString(connectionString);
   _azureTopic.RetryPolicy = RetryPolicy.NoRetry;
}

var brokeredMessage = new BrokeredMessage(message.Message)
{
    MessageId = message.Id.ToString()
};
brokeredMessage.Properties["ReceivedTimestamp"] = DateTime.Now;

_azureTopic.Send(brokeredMessage);

<End Loop>

注意: 我们制定 NoRetry 政策是有原因的。不想给问题增加太多噪音,失败的相同消息将在下一次迭代中再次尝试(它以循环方式将消息发送给订阅者)。

小时间窗口内的错误日志示例。

20:31:51 Event.WindowsService Event.WindowsService::PublishAzureServiceBusTopicMessage() 尝试与 Azure 同步消息时出错。留言编号:1191251
与服务总线通信时出错。检查连接 信息,然后重试。

20:32:00 Event.WindowsService Event.WindowsService::PublishAzureServiceBusTopicMessage() 尝试与 Azure 同步消息时出错。留言编号:1191251
没有这样的主机是已知的

20:32:00 RFID.WindowsService RFID.WindowsService::PublishAzureServiceBusTopicMessage() 尝试与 Azure 同步消息时出错。留言编号:1930029
没有这样的主机是已知的

20:32:10 RFID.WindowsService RFID.WindowsService::PublishAzureServiceBusTopicMessage() 尝试与 Azure 同步消息时出错。留言编号:1930029
没有这样的主机是已知的

20:32:10 Event.WindowsService Event.WindowsService::PublishAzureServiceBusTopicMessage() 尝试与 Azure 同步消息时出错。留言编号:1191251
没有这样的主机是已知的

20:32:10 RFID.WindowsService RFID.WindowsService::PublishAzureServiceBusTopicMessage() 尝试与 Azure 同步消息时出错。留言编号:1930029
没有这样的主机是已知的

20:34:00 RFID.WindowsService RFID.WindowsService::PublishAzureServiceBusTopicMessage() 尝试与 Azure 同步消息时出错。消息 ID:1930034
与服务总线通信时出错。检查连接 信息,然后重试。

20:38:34 Event.WindowsService Event.WindowsService::PublishAzureServiceBusTopicMessage() 尝试与 Azure 同步消息时出错。留言编号:1191269
与服务总线通信时出错。检查连接 信息,然后重试。

20:38:51 RFID.WindowsService RFID.WindowsService::PublishAzureServiceBusTopicMessage() 尝试与 Azure 同步消息时出错。消息 ID:1930043
与服务总线通信时出错。检查连接 信息,然后重试。

【问题讨论】:

  • RetryPolicy 是要走的路
  • 很遗憾,我们不能等待重试策略。如果消息失败,我们需要将消息发送给第二个本地订阅者(然后返回再次尝试发送给第一个 Azure 订阅者)。
  • 您可以将客户端配置为仅重试一次,然后将其发送回本地订阅者。没有重试策略的根本原因是什么?
  • 我们不想重试,因为我们无法等待向我们的第二个订阅者发送相同的消息。所以本质上,在循环中它将发送到 Azure,然后发送到本地的另一个 WCF 服务。如果它无法发送到 Azure,那么它仍然必须继续发送到 WCF 服务(没有任何延迟)。我们分别跟踪发送到 azure 和 wcf 的内容,因此当循环返回发送到 azure 时,它​​将重试发送失败的相同消息。
  • 重试策略仅适用于瞬态故障,因此消息不会被传递两次。您还可以配置重试之间的延迟

标签: c# azure network-programming azureservicebus


【解决方案1】:

服务总线在 Namespace Manager、Messaging Factory 和 Client 上具有本机重试功能(请参阅 Retry guidance for specific services)。

因为它正在处理瞬态异常,所以您不应该重复发送消息。

如果你只想重试一次你可以这样配置:

var connectionString = "myconnectionstring";
var client = TopicClient.CreateFromConnectionString(connectionString);
client.RetryPolicy = new RetryExponential(minBackoff: TimeSpan.FromSeconds(2),
                                        maxBackoff: TimeSpan.FromSeconds(2),
                                        maxRetryCount: 1);

这应该可以解决问题。

如果要确保重复数据删除,只需 google azure servicebus deduplication。

【讨论】:

  • 谢谢托马斯。我会尝试重试策略。只要它的策略很短并且只尝试一次,就可以了。需要与商家核实这一点。但可能会在下周尝试,如果问题有所改善,请告知您
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-14
  • 1970-01-01
  • 2018-09-19
相关资源
最近更新 更多