【发布时间】: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