我有一系列网站(异步)将事件分析发送到ASP.NET网站,然后该网站应将事件发送到Azure EventHubs实例。
我面临的挑战是,当请求超过每秒50,000次时,我注意到我服务这些请求的响应时间是在多秒范围内,影响了初始发送网站的总加载时间。我已经扩展了所有部分但是我认识到,由于打开与事件中心的AMQP连接并发送有效负载的开销,每个请求发送一个事件效率不高。
作为一种解决方案,我一直在尝试批量发送到我的EventHubs实例的事件数据,但是我遇到了一些同步问题。对于每个请求,我将事件数据添加到通过EventDataBatch
和EventHubClient.CreateBatch()
创建的静态eventHubData.TryAdd()
中,然后我检查事件的数量是否在预定义的阈值内,如果是,我通过EventHubClient.SendAsync()
异步发送事件。这带来的挑战是,由于这是一个ASP .NET应用程序,可能有许多线程试图在任何给定的实例上提供请求 - 其中任何一个都可能在同一时间点尝试eventHubData.TryAdd()
或EventHubClient.SendAsync()
。我尝试在lock(batch)
之前尝试调用eventHubData.TryAdd()
,但是这并没有解决问题,因为我无法锁定异步方法EventHubClient.SendAsync()
。
实现此解决方案的最佳方法是什么,以便每个请求都不需要它自己对事件中心的请求,并且可以利用批处理同时保持批处理本身的完整性而不会遇到任何死锁问题?
查看应用程序洞察SDK的源代码,了解它们如何解决这个问题 - 您可以重用其中的关键部分来实现事件集线器AMQP的相同功能。
模式是,
1)缓冲数据。定义一个缓冲区,您将在具有最大大小的线程之间共享。多个线程将数据写入缓冲区
2)准备传输。您可以在缓冲区已满,某个时间间隔过去或先发生的任何一个时间内传输缓冲区中的项目。从缓冲区中取出所有项目以进行发送
3)做传输。在一个Event Hub消息中将所有项目作为多个数据点发送,
它们是通过使用HTTP发布到Application Insights集合端点来实现此目的的3个类 - 您可以看到如何应用样本模式来收集,合并和传输到事件中心。
您需要控制最大邮件大小,即每个事件中心消息256KB,您可以通过设置遥测缓冲区大小来实现 - 这取决于您的客户端逻辑来管理它。