我正在编写代码,使用Azure Event Hub将来自多个线程的消息发布到C#中的EventHubClient。 EventHubClient的文档包含相当标准的样板。
"此类型的任何公共静态(在Visual Basic中为Shared)成员都是 线程安全。任何实例成员都不能保证是线程 。安全"
the four send中的任何一个都没有关于线程安全的其他文档 methods我最希望线程安全。我是否相信发送方法不是线程安全的,那么每次我希望发送消息时,我最终都会创建一个新的EventHubClient实例。由于除非采取了步骤,否则将重用基础tcp连接apparently,这可能不会产生太多开销。类似的问题出现在partitioned senders但是假设有一个异步方法来创建一个,它们可能有自己的AMQP连接。
尽管有文档,EventHubClient线程的一些(如果不是全部)实例方法是否安全?
对于任何Azure人员,是否可以在文档中澄清这一点?这种文档问题(假设它看起来很可能)似乎也出现在affect Azure Table中,并且通常在MSDN文档中很常见。关于EventHub,这与Kafka和AWS Kinesis的明确的线程安全声明相反,至少没有明确地将所有内容标记为不安全。我没有在SDK的开源部分找到EventHubs,因此无法检查自己。
答案 0 :(得分:6)
TLDR :
EventHubClient
对象一次并重新使用
故事
ServiceBus SDK公开了两种模式来创建发件人:
对于Basic版本 - 开发人员将直接使用EventHubClient.CreateFromConnectionString()
API,而不用担心管理MessagingFactory
个对象(连接gu)。只要MessagingFactory
相同 - 所有键和值的字面匹配 - 在SDK中完成此重用,SDK将处理在所有EventHubClient
实例中重用connection string
的处理。
对于需要在连接级别进行更多控制的高级开发人员,SB SDK提供MessagingFactory.CreateFromConnectionString()
,并且此开发人员可以创建EventHubClient
实例。
发送到EventHubs的EventHubClient
的所有实例方法严格线程安全。通常,所有数据平面操作都是......
但是,在从EventHubs读取时,API已针对此模式进行了优化。
while(true) {
var events = eventHubPartitionReceiver.receive(100);
processMyEvents(events);
}
因此,对于ex:EventHubReceiver.RuntimeInformation
等属性在每次receive
调用之后填充,而不进行任何同步。因此,即使实际的receive
API是线程安全的 - 后续调用RuntimeInformation也不是 - 因为很少有人在receive
的实例上停放多个PartitionReceiver
调用
在每个组件中创建EventHubClient
的新实例以开始发送消息是默认模式 - ServiceBus SDK将负责重用基础MessagingFactory - 它重用相同的物理套接字(如果连接字符串是相同)。
如果您正在寻找真正的高吞吐量方案,那么您应该设计一个策略来创建多个MessagingFactory对象,然后分别创建一个EventHubClient。但是 - 在尝试此操作之前,请确保已经增加了Portal上EventHub的Thruput单位,因为默认值仅为1 MBPS - 累计所有16个分区。
此外,如果您使用的发送模式是分区发件人 - 如果您使用相同的 eventHubClient (。CreatePartitionedSender())实例创建所有发件人,则它们也将使用相同的基础MessagingFactory。