I\'m writing code that will be publishing messages from multiple threads to an Azure Event Hub in C# using the EventHubClient. The documentation for EventHubClient contains
TLDR:
EventHubClient
object once and re-useThe Story
ServiceBus SDK exposes two patterns to create senders:
For Basic version - developer will directly use EventHubClient.CreateFromConnectionString()
API and doesn't worry about managing MessagingFactory
objects (connection gu's). SDK will handle reusing the MessagingFactory
across all EventHubClient
instances as long as the connection string
is same - a literal match of all keys and values - is done in the SDK for this reuse.
For an Advanced developer who will need a bit more control at connection level, SB SDK provides MessagingFactory.CreateFromConnectionString()
and from this developer can create the EventHubClient
instance.
All instance methods of EventHubClient
- to send to EventHubs are strictly thread-safe. In general, all data-plane operations are...
However, while reading from EventHubs, API is optimized for, this pattern.
while(true) {
var events = eventHubPartitionReceiver.receive(100);
processMyEvents(events);
}
So, for ex: properties like, EventHubReceiver.RuntimeInformation
- is populated after every receive
call without any synchronization. So, even though the actual receive
API is thread-safe - the subsequent call to RuntimeInformation isn't - as it is rare for anyone to park multiple receive
calls on an instance of PartitionReceiver
.
Creating a new instance of EventHubClient
in each component to start send messages is the default pattern - and the ServiceBus SDK will take care of reusing the underlying MessagingFactory - which reuses the same physical socket (if the connection string is same).
If you are looking for real high throughput scenarios then you should design a strategy to create multiple MessagingFactory objects and then Create an EventHubClient each. However - make sure that you have already increased the Thruput units for your EventHub on the Portal before trying this as the default is just 1 MBPS - cumulative of all 16 partitions.
Also, if the Send pattern you are using is Partitioned Senders - they all will also use the same underlying MessagingFactory - if you create all Senders from the same eventHubClient(.CreatePartitionedSender()) instance.