Azure EventHub - EventHubClient.Send() 导致 NullReferenceException
Azure EventHub - EventHubClient.Send() results in NullReferenceException
简短版本:NullReferenceException
使用 EventHubClient.SendBatch
将数据发送到 EventHub。为什么连接被断开?
更长的解释:
我正在尝试使用 C# 中 EventHubClient
class 的 SendBatch
方法将数据发送到 EventHub
。 (https://docs.microsoft.com/en-us/dotnet/api/microsoft.servicebus.messaging.eventhubclient)
批量大小为 100 个 json 个对象,不应太大。我在更大和更小的批量大小上都遇到过同样的问题。我也试过使用 Send()
来一个一个地发送对象。同样的结果。
这在 99% 的情况下都很好,但有时会导致 NullReferenceException
,留下以下堆栈跟踪:
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.ServiceBus.Messaging.MessageSender.RetrySenderEventDataAsyncResu
lt.<>c.<.ctor>b__5_0(EventData e)
at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate
)
at Microsoft.ServiceBus.Messaging.MessageSender.RetrySenderEventDataAsyncResu
lt..ctor(MessageSender sender, TrackingContext trackingContext, IEnumerable`1 me
ssages, TimeSpan timeout, AsyncCallback callback, Object state)
at Microsoft.ServiceBus.Messaging.MessageSender.BeginSendEventData(TrackingCo
ntext trackingContext, IEnumerable`1 eventDatas, TimeSpan timeout, AsyncCallback
callback, Object state)
at Microsoft.ServiceBus.Messaging.EventHubClient.SendBatch(IEnumerable`1 even
tDataList)
我尝试实施重试政策,两者都使用
EventHubClient.RetryPolicy = RetryPolicy.Default;
并通过使用 Thread.Sleep(n)
手动执行递归方法调用,以提供重新建立连接的时间。
有时连接会在 10 秒后恢复,有时会在 60 秒后恢复,通常永远不会(或者直到我对该方法的递归调用达到 WhosebugException
,大约 30 分钟后,但取决于多长时间线程进入休眠状态)。从逻辑上讲,我的系统不能有这个不稳定的部分。
任何人都知道为什么会发生此异常,是否是由于连接断开?
这里的答案竟然是一个重载的EventHub。
每第 100 个批次,等待 0.5 秒。对于每个 NullReferenceException,请等待 2 秒,然后再尝试使用相同的数据。在连接恢复之前,可能需要重试 100 多次。我尝试了指数等待时间,但在我的案例中没有成功(最终等待了几个小时,但仍然没有连接)。
当然 - 在 C#
中使用永恒的 while 循环而不是递归调用。这可以防止 WhosebugException
。 (菜鸟错误)。
工作代码:
public bool SendMessageAsList(List<EventData list)
{
while(true)
{
var batchList = new List<EventData>();
for (var i = 0; i < list.Count; i + 100)
try
{
if (i % 10000)
Thread.Sleep(500);
batchList = list.Skip(i).Take(100).ToList();
EventHubClient.SendBatch(batchList);
// Gets here at success
list = list.Skip(100).ToList();
if (batchList.Count < 100)
break;
}
catch (NullReferanceException e)
{
Console.WriteLine(e);
Thread.Sleep(2000)
}
}
简短版本:NullReferenceException
使用 EventHubClient.SendBatch
将数据发送到 EventHub。为什么连接被断开?
更长的解释:
我正在尝试使用 C# 中 EventHubClient
class 的 SendBatch
方法将数据发送到 EventHub
。 (https://docs.microsoft.com/en-us/dotnet/api/microsoft.servicebus.messaging.eventhubclient)
批量大小为 100 个 json 个对象,不应太大。我在更大和更小的批量大小上都遇到过同样的问题。我也试过使用 Send()
来一个一个地发送对象。同样的结果。
这在 99% 的情况下都很好,但有时会导致 NullReferenceException
,留下以下堆栈跟踪:
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.ServiceBus.Messaging.MessageSender.RetrySenderEventDataAsyncResu
lt.<>c.<.ctor>b__5_0(EventData e)
at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate
)
at Microsoft.ServiceBus.Messaging.MessageSender.RetrySenderEventDataAsyncResu
lt..ctor(MessageSender sender, TrackingContext trackingContext, IEnumerable`1 me
ssages, TimeSpan timeout, AsyncCallback callback, Object state)
at Microsoft.ServiceBus.Messaging.MessageSender.BeginSendEventData(TrackingCo
ntext trackingContext, IEnumerable`1 eventDatas, TimeSpan timeout, AsyncCallback
callback, Object state)
at Microsoft.ServiceBus.Messaging.EventHubClient.SendBatch(IEnumerable`1 even
tDataList)
我尝试实施重试政策,两者都使用
EventHubClient.RetryPolicy = RetryPolicy.Default;
并通过使用 Thread.Sleep(n)
手动执行递归方法调用,以提供重新建立连接的时间。
有时连接会在 10 秒后恢复,有时会在 60 秒后恢复,通常永远不会(或者直到我对该方法的递归调用达到 WhosebugException
,大约 30 分钟后,但取决于多长时间线程进入休眠状态)。从逻辑上讲,我的系统不能有这个不稳定的部分。
任何人都知道为什么会发生此异常,是否是由于连接断开?
这里的答案竟然是一个重载的EventHub。
每第 100 个批次,等待 0.5 秒。对于每个 NullReferenceException,请等待 2 秒,然后再尝试使用相同的数据。在连接恢复之前,可能需要重试 100 多次。我尝试了指数等待时间,但在我的案例中没有成功(最终等待了几个小时,但仍然没有连接)。
当然 - 在 C#
中使用永恒的 while 循环而不是递归调用。这可以防止 WhosebugException
。 (菜鸟错误)。
工作代码:
public bool SendMessageAsList(List<EventData list)
{
while(true)
{
var batchList = new List<EventData>();
for (var i = 0; i < list.Count; i + 100)
try
{
if (i % 10000)
Thread.Sleep(500);
batchList = list.Skip(i).Take(100).ToList();
EventHubClient.SendBatch(batchList);
// Gets here at success
list = list.Skip(100).ToList();
if (batchList.Count < 100)
break;
}
catch (NullReferanceException e)
{
Console.WriteLine(e);
Thread.Sleep(2000)
}
}