是什么导致Azure事件中心ReceiverDisconnectedException / LeaseLostException?
我正在使用EventProcessorHost和一个IEventProcessor类(调用它:MyEventProcessor)从EventHub接收事件。 我通过在两台服务器上运行我的EPH,并使用相同的ConsumerGroup连接到Hub,但使用唯一的hostName(使用机器名称)将其扩展到两台服务器。
问题是:在白天/黑夜的随机时间,应用程序记录此:
Exception information: Exception type: ReceiverDisconnectedException Exception message: New receiver with higher epoch of '186' is created hence current receiver with epoch '186' is getting disconnected. If you are recreating the receiver, make sure a higher epoch is used. at Microsoft.ServiceBus.Common.ExceptionDispatcher.Throw(Exception exception) at Microsoft.ServiceBus.Common.Parallel.TaskHelpers.EndAsyncResult(IAsyncResult asyncResult) at Microsoft.ServiceBus.Messaging.IteratorAsyncResult`1.StepCallback(IAsyncResult result)
此exception与LeaseLostException同时发生,当它尝试检查点时,从MyEventProcessor的CloseAsync方法抛出。 (由于ReceiverDisconnectedException,可能正在调用Close?)
我认为这是由于Event Hubs在扩展到多台机器时的自动租赁管理而发生的。 但我想知道我是否需要做一些不同的事情,以使其工作更干净,避免这些例外? 例如:有时代的东西?
TLDR :这种行为绝对正常。
为什么租赁管理不能平稳无exception :为开发人员提供更多控制。
真正的长篇故事 – 从Basics EventProcessorhost
(特此是EPH
– 非常类似于__consumer_offset topic
为Kafka Consumers
做的__consumer_offset topic
– 分区所有权和检查点存储)是由Microsoft Azure EventHubs
团队自己编写的 – 用于翻译所有EventHubs partition receiver Gu
成一个简单的onReceive(Events)
回调。
在读取像EventHubs
这样的高吞吐量分区流时, EPH
用于解决2个一般的,主要的,众所周知的问题:
-
容错接收管道 – 例如:问题的更简单版本 – 如果运行
PartitionReceiver
的主机死亡并返回 – 它需要从它离开的地方继续处理。 为了记住上次成功处理的EventData
,EPH
使用提供给EPH
构造函数的blob
来存储检查点 – 用户何时调用context.CheckpointAsync()
。 最终,当主机进程终止时(例如:突然重新启动或命中硬件故障并且永远不会/恢复) – 任何EPH
实例都可以接收此任务并从该Checkpoint
恢复。 -
在
EPH
实例之间平衡/分配分区 – 假设,如果有10个分区和2个EPH
实例处理来自这10个分区的事件 – 我们需要一种方法来跨实例划分分区(EPH
库的PartitionManager
组件执行此操作)。 我们使用Azure Storage - Blob LeaseManagement-feature
来实现此Azure Storage - Blob LeaseManagement-feature
。 从版本2.2.10
– 为了简化问题,EPH
假定所有分区都被平均加载 。
有了这个,让我们试着看看发生了什么:首先,在上面的10
事件中心分区示例和2
EPH
实例中处理事件:
- 让我们说第一个
EPH
实例 –EPH1
启动,单独启动,启动的一部分,它创建了所有10个分区的接收器并处理事件。 在启动时 –EPH1
将宣布它拥有所有这10
分区,通过获取10
存储blob上的租约代表这10
事件中心分区(具有标准nomenclature
–EPH
内部在存储帐户中创建 – 从传递给ctor
的StorageConnectionString
)。 租约将在规定的时间内获得 ,之后EPH
实例将失去该分区的所有权。 -
EPH1
不断announces
– 它仍然拥有这些分区 – 通过renewing
blob上的租约。 可以使用PartitionManagerOptions
执行renewal
频率以及其他有用的调整 - 现在,假设,
EPH2
启动 – 并且您也向EPH1
的ctor
提供了与EPH1
相同的AzureStorageAccount
。 现在,它有0
分区要处理。 因此,为了实现EPH
实例之间的分区平衡,它将继续download
所有具有owner
映射到partitionId
leaseblobs
的列表。 从这一点来看,STEAL
租赁它的公平份额的partitions
– 在我们的例子中是5
,并将宣布该lease blob
。 作为其中的一部分,EPH2
读取PartitionX
编写的最新检查点,它想要窃取租约并继续创建相应的PartitionReceiver
,其EPOCH
与Checkpoint
。 - 因此,
EPH1
将失去这5个partitions
所有权,并将根据其所处的确切状态遇到不同的错误。- 如果
EPH1
实际上正在调用PartitionReceiver.Receive()
调用 – 当EPH2
在同一个接收器上创建PartitionReceiver
时 –EPH1
将遇到ReceiverDisconnectedException 。 这最终会调用IEventProcessor.Close(CloseReason=LeaseLost)
。 请注意,如果接收的消息较大或PrefetchCount
较小,则达到此特定exception的概率较高 – 因为在这两种情况下接收器将执行更具侵略性的I / O. - 如果
EPH1
处于checkpointing
lease
或renewing
lease
,而EPH2
stole
了租约,EventProcessorOptions.ExceptionReceived
eventHandler将通过leaselostException
(在leaseblob
上发生409
冲突错误)发出信号 – 这最终也会调用IEventProcess.Close(LeaseLost)
。
- 如果
为什么租赁管理不能顺利和免除 :
为了使消费者保持简单和无差错, EPH
可以吞下与租赁管理相关的exception,而根本不会通知用户代码。 然而,我们意识到,抛出LeaseLostException
可以让客户在IEventProcessor.ProcessEvents()
回调中找到有趣的错误 – 症状就是 – 频繁的分区移动
- 特定机器上的小型网络中断 – 由于
EPH1
无法renew
租约并重新启动! – 想象一下,如果这台机器的n / w在一天内EPH
–EPH
实例将与Partitions
一起打ping-pong
! 这台机器将不断尝试从其他机器窃取租约 – 从EPH
角度来看这是合法的 – 但是,这对于EPH
的用户来说是完全的灾难 – 因为它完全干扰了处理管道。EPH
– 当n / w重新启动这个片状m / c时,会看到一个ReceiverDisconnectedException
! 我们认为最好也是事实上唯一的方法是让开发人员闻到这一点! - 或者一个简单的场景,例如,在
ProcessEvents
逻辑中有一个错误 – 它会抛出未处理的exception,这些exception是致命的并且会导致整个过程 – 例如:毒害事件。 这个分区将会移动很多。 - 客户,在
EPH
也在使用的同一存储帐户上执行写入/删除操作 – 错误(如自动清理脚本)等。 - 最后但并非最不重要 – 我们永远不希望发生这种情况 – 比如在Azure dc上发生5分钟的
outage
,其中有一个特定的EventHub.Partition
– 比如n / w事件。 分区将在EPH
实例中移动。
基本上,在大多数情况下,对我们来说检测差异会很棘手。 在这些情况和合法租约之间由于平衡导致丢失,我们希望将这些情况的控制委托给开发人员。
请参阅我们的PM Dan的博客,以获得一般概述。
- Asp.net Identity使用密码和Azure Active Directory身份validation
- C#JsonConvert.DeserializeAnonymousType失败
- 如何使用Azure流畅的资源管理注册资源提供程序?
- 将Azure ServiceBus上的消息从.NET Core发送器发送到.NET 4.6处理程序
- 在azure上发布时列名无效
- QueueClient.Receive()的异步方法?
- Azure共享访问签名 – 签名不匹配
- 如何更新Azure Notification Hub注册中的到期时间?
- 如何使用超时Azure Web App的长响应来防止HttpWebRequest