Monday, August 13, 2018

Creating a MassTransit client/server application using RabbitMQ, .Net Core and Linux

On a previous post we introduced MassTransit on this blog and presented and some reasons why it may be a real nice alternative to your system.

Today we will review a simple use case: I will simulate a client/server arquitecture by building two console applications using MassTransit as the service bus, RabbitMQ as the transport running on Docker, .Net Core and Linux.

Sounds complicated? Let's take a look.

Installing RabbitMQ

So, the first and main dependency that we have is RabbitMQ. Because installing RabbitMQ may not be so simple, why not use a Docker image instead?

Assuming you have docker installed on your machine, pulling a RabbitMQ image is as simple as:
$ docker run --hostname rmqhost --name rmqcontainer -p 15672:15672 -p 5672:5672 rabbitmq:3.7.5-management
Before running that command, let's examine what each part means:
  • --hostname rmqhost : sets the host name
  • --name rmqcontainer : sets the name of the container
  • -p 15672:15672 : maps container port 15672 to host port 15672 so you can access on your localhost
  • -p 5672:5672 : maps container port 5672 to host port 5672 so you can access on your localhost
  • rabbitmq:3.7.5-management : the name of the image to donwload and run. I chose that one because it has a nice UI to manage RabbitMQ in case you want to play with it.

If you don't have that image yet, Docker will pull it for you and initialize a container based on the parameters above. Once the download is complete, Docker will init RabbitMQ for us. On my Fedora box, I get:


If you've got an output similar to mine, your RabbitMQ Docker image is loaded and you can then access RabbitMQ's Management UI on http://localhost:15672:

Type guest/guest as username/password, and you should be logged in:
Cool. Now that we have RabbitMQ running, let's take a look at MassTransit.

Building a shared .Net POCO Contract

Since we're building a client and a server, we also need to build a shared contract they can access. Because the client and the server may (and should) run on different servers, the common solution is to build a class library and reference it on both projects.

In .Net Core we simply type in the terminal:
dotnet new console -n MassTransit.RabbitMQ.Contracts
Then open that project and add this simple message:
That's it. Build that project to validate everything is ok and let's move to the client.

Building a MassTransit RabbitMQ Client

As previously said, the client will need to do two important things:
  • connect to the bus so it can start sending messages
  • send messages that the server recognizes. That's why we created the contract on the step above.

You can initialize your client with a command similar to the one executed above. Once you have your project created, the important bits are: adding a reference to the contract project previously created, initializing the bus and publishing a message to RabbitMQ.

Initializing the bus

To initialize the bus, write a code similar to:

Publishing a message to RabbitMQ

Now, we should be able to publish a message with a code like: Build this project with $ dotnet build to make sure everything is ok but don't run it yet. We still need to build the server.

Building a MassTransit RabbitMQ Server

The simple server is pretty similar to the client with the difference that:
  • the server does not publish messages
  • the server contains handlers (consumers) to messages published
Build a new console app and reference the contract project created above.

This gist shows how to init a service that will run on a console terminal and handle the CreateAccount message:

Let's Test!

Now, let's test both the client and the server to see if they're working ok. Don't forget that now you'll need your RabbitMQ instance running. I suggest running the apps side by side and let's see how that goes:

My Client App:
 My Server App:

And my RabbitMQ console:


So, from the above, you see that the messages sent from the client are reaching the server. Remember, those applications do not know about each other and the only coupling between them is the standalone contract project that both references.

Conclusion

That's it! My first experience with MassTransit was a breeze. I'm very satisfied so far with my experience with this framework and will probably write a post or two more to details other use cases (mainly sagas and error handling).

Feel free to download the source code used on this post directly from my GitHub page.

See Also

MassTransit, a real alternative to NServiceBus?
Creating a MassTransit client/server application using RabbitMQ, .Net Core and Linux
Exploring MassTransit InMemory Scheduled Messaging using RabbitMQ and .Net Core
Why you should start using .Net Core
Building and Running Asp.Net Core apps on Linux
.NET Core and .NET merging as .NET 5.0

For more posts on MassTransit, please click here.