Over a million developers have joined DZone.

EasyNetQ: A Breaking Change, IPublishChannel

DZone's Guide to

EasyNetQ: A Breaking Change, IPublishChannel

· Integration Zone ·
Free Resource

Discover how you can get APIs and microservices to work at true enterprise scale.

EasyNetQ is my high-level .NET API for RabbitMQ.

Until recently, to publish a message using EasyNetQ you would create an instance of IBus and then call the publish method on it:


The IBus instance is the logical representation of a connection to a RabbitMQ server. Generally you should open a connection to the RabbitMQ server when your service (or application) starts and close it when the service shuts down. AMQP (the messaging protocol that RabbitMQ implements) multiplexes operations over the connection using channels, so while the connection is open, multiple channels can be opened and closed to carry out AMQP operations.

Initially I’d hoped to hide channels from EasyNetQ users. With subscriptions this makes sense - after the client creates a subscription, EasyNetQ looks after the channel and the subscription consuming thread. But publishing turned out to be more complex. Channels cannot be shared between threads, so EasyNetQ initially used a ThreadLocal channel for all publish calls. A new thread meant a new channel.

This problem manifested itself with a nasty operational bug we suffered. We had a service which woke up on a timer, created some threads, and published messages on them. Although the threads ended, the channels didn’t close, and each timer interval added another few open channels. After a period of time the channel count exceeded the allowed maximum and our RabbitMQ server died. Initially we considered finding some way of discovering when a thread ends and then disposing the channels based on some trigger, but after a discussion on Stack Overflow, we came around to the view that a sensible API design hands the responsibility of managing the channel lifetime to the API’s consumer (thanks to Martin James for being the main persuader).

So let me introduce you to my new friend, IPublishChannel. Instead of calling Publish directly on the IBus instance, EasyNetQ clients now have to create an instance of IPublishChannel and call its Publish method instead. IPublishChannel, as its name suggests, represents a channel. The channel is opened when it’s created, and disposed when it’s disposed.

Here’s how you use it:

using (var publishChannel = bus.OpenPublishChannel())

So a little more API complexity, but a lot more transparency about how channels are created and disposed.

The request/response API has also changed to include IPublishChannel:

using (var publishChannel = bus.OpenPublishChannel())
    publishChannel.Request<TestRequestMessage, TestResponseMessage>(request, response => 
        Console.WriteLine("Got response: '{0}'", response.Text));

The EasyNetQ version has been bumped to 0.5 to reflect the breaking change.

Happy messaging!

APIs and microservices are maturing, quickly. Learn what it takes to manage modern APIs and microservices at enterprise scale.


Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}