Introduction to NServiceBus: Getting started

The best way to get started with NServiceBus is to use it to build something realistic. In doing so you'll learn the architectural concepts behind the software, and start to learn its capabilities. In this tutorial, you'll be building a back end for a retail e-commerce system. You'll learn how to send asynchronous messages between processes, how to use the Publish/Subscribe pattern to decouple business processes, and the advantages of using reliable messaging to enable automatic retries after processing failures.

The tutorial is divided into five lessons, each of which can be accomplished in a half hour or less — perfect for your lunch break.

In this first lesson, which should take 10-15 minutes, you will learn how to set up a new development machine for NServiceBus and create your very first messaging endpoint.

Before we get started

NServiceBus has very few prerequisites. All it needs is the .NET Framework and message queuing infrastructure.

Although NServiceBus only requires .NET Framework 4.5.2, this tutorial uses Visual Studio 2015 and .NET Framework 4.6.1, which includes some useful async-related APIs.

NServiceBus needs queuing infrastructure (a transport) to move messages around. By default, this tutorial will use Microsoft Message Queuing (MSMQ), which is included with every version of Windows, although it is not installed by default.

If MSMQ is not an option for your environment, the SQL Server Transport can be used as a message transport instead. To get started using SQL Server instead of MSMQ, review the SQL Server transport setup instructions. Throughout the rest of the tutorial, instructions that differ between the SQL and MSMQ transports will be highlighted in an informational box like this one.

To install MSMQ on your machine, you have two options:

It's enough at this point to simply install the Platform Installer tools. At the end of the install process, a button will offer the option to start ServiceControl Management to install or update a ServiceControl instance. This isn't required right now, but we'll return to this topic in Lesson 5 when we explore how to replay failed messages.

Exercise

Let's build something simple to give NServiceBus a try.

Create a solution

First, let's create a basic solution and include the dependencies we need.

  1. In Visual Studio, create a new project and select the Console Application project type.
  2. Set the project name to ClientUI.
  3. Set the solution name to RetailDemo.

Next, we need to add the NServiceBus NuGet package as a dependency. From the NuGet Package Manager Console, type the following:

Install-Package NServiceBus -ProjectName ClientUI

This adds a reference to the NServiceBus.Core assembly to the project.

If you are using the SQL Server transport, you also need to install the NServiceBus.SqlServer package before continuing. See Using the SQL Server transport - Adding the NuGet package for more details.

With the proper dependencies in place, we're ready to start writing code.

Configure an endpoint

Now we're ready to create a messaging endpoint. A messaging endpoint (or just endpoint) is a logical component that's capable of sending and receiving messages. An endpoint is hosted within a process, which in this case is a simple console application, but could be a web application or other .NET process.

Because of the current limitations of console applications, we need to add some boilerplate code to be able to use the async/await keywords.

In the Program.cs file, modify the code to look like the following:

Edit
class Program
{
    static void Main()
    {
        AsyncMain().GetAwaiter().GetResult();
    }

    static async Task AsyncMain()
    {

    }
}

Add the following code to your program first and then let's analyze the importance of each line.

Add this code to your AsyncMain method:

Edit
static async Task AsyncMain()
{
    Console.Title = "ClientUI";

    var endpointConfiguration = new EndpointConfiguration("ClientUI");

    var transport = endpointConfiguration.UseTransport<MsmqTransport>();

    endpointConfiguration.UseSerialization<JsonSerializer>();
    endpointConfiguration.UsePersistence<InMemoryPersistence>();
    endpointConfiguration.SendFailedMessagesTo("error");
    endpointConfiguration.EnableInstallers();
}

Now, let's go line-by-line and find out exactly what each step is doing.

Console Title

Edit
Console.Title = "ClientUI";

When running multiple console apps in the same solution, giving each a name makes them easier to identify. This console app's title uses ClientUI. In later lessons, we'll expand this solution to host several more.

EndpointConfiguration

Edit
var endpointConfiguration = new EndpointConfiguration("ClientUI");

The EndpointConfiguration class is where we define all the settings that determine how our endpoint will operate. The single string parameter ClientUI is the endpoint name, which serves as the logical identity for our endpoint, and forms a naming convention by which other things will derive their names, such as the input queue where the endpoint will listen for messages to process.

Transport

Edit
var transport = endpointConfiguration.UseTransport<MsmqTransport>();

This setting defines the transport that NServiceBus will use to send and receive messages. We are using the MsmqTransport, which is bundled within the NServiceBus core library. All other transports require different NuGet packages.

Capturing the transport settings in a variable as shown will make things easier in Lesson 3 when we start defining message routing rules.

If using the SQL Server transport, you must use the SqlServerTransport and provide a connection string to the database. See Using the SQL Server transport - Configuring the transport for more details.

Serializer

Edit
endpointConfiguration.UseSerialization<JsonSerializer>();

When sending messages, an endpoint needs to serialize message objects to a stream, and then deserialize the stream back to a message object on the receiving end. The choice of serializer governs what format that will take. Each endpoint in a system needs to use the same serializer in order to be able to understand each other.

Here, we are choosing the JsonSerializer because JSON is reasonably compact and efficient, while still being human-readable. When using JSON, it's also easier to integrate with other systems on other platforms due to its ubiquity.

Persistence

Edit
endpointConfiguration.UsePersistence<InMemoryPersistence>();

A persistence is required to store some data in between handling messages. We will explore the reasons for this in future lessons but for now, we'll use an implementation that stores everything in memory. This has the advantage during development of allowing us to iterate quickly by providing us with a clean slate every time we start up. Of course, as everything persisted is lost when the endpoint shuts down, it is not safe for production use, so we will want to replace it with a different persistence option before deployment.

Error queue

Edit
endpointConfiguration.SendFailedMessagesTo("error");

Processing a message can fail for several reasons. It could be due to a coding bug, a database deadlock, or unanticipated data inside a message. Automatic retries will make dealing with non-deterministic exceptions a non-issue, but for very serious errors, the message could get stuck at the top of the queue and be retried indefinitely. This type of message, known as a poison message, would block all other messages behind it. When these occur, NServiceBus needs to be able to set it aside in a different queue to allow other work to get done. This queue is referred to as the error queue and is commonly named error. We will discuss recoverability more in Lesson 5: Retrying errors.

Installers

Edit
endpointConfiguration.EnableInstallers();

This setting instructs the endpoint to run installers on startup. Installers are used to set up anything the endpoint requires to run. The most common example is creating necessary queues, such as the endpoint's input queue where it will receive messages.

Starting up

At the end of the AsyncMain method, after the configuration code, add the following code which will start up the endpoint, keep it running until we press the Enter key, and then shut it down.

Edit
var endpointInstance = await Endpoint.Start(endpointConfiguration)
    .ConfigureAwait(false);

Console.WriteLine("Press Enter to exit...");
Console.ReadLine();

await endpointInstance.Stop()
    .ConfigureAwait(false);
In this tutorial we will always use .ConfigureAwait(false) when awaiting tasks, in order to avoid capturing and restoring the SynchronizationContext.

The endpoint is initialized according to the settings defined by the EndpointConfiguration class. Once the endpoint starts, changes to the configuration information are no longer applied.

When you run the endpoint for the first time, the endpoint will:

  • Display its logging information, which is written to a file as well as the console. NServiceBus also logs to multiple levels, so you can change the log level from INFO to log level DEBUG in order to get more information.
  • Display the status of your license.
  • Attempt to add the current user to the "Performance Monitor Users" group so that it can write performance counters to track its health and progress.
  • Create several queues:, if they do not already exist:
    • error
    • clientui
    • clientui.retries
    • clientui.timeouts
    • clientui.timeoutsdispatcher

Now might be a good time to go look at your list of queues. There are a variety of options for viewing MSMQ queues and messages that you can pick from. In addition to the queues mentioned above, you may also see an error.log queue and queues starting with particular.servicecontrol if you installed a ServiceControl instance while installing the Particular Service Platform.

When using the MSMQ transport, queues are created with permissive settings that make things easier during development. In a production scenario these queues should be created with the minimum required privileges. The endpoint will write a log entry on startup when permissive settings are detected to remind you to do this.

If you are using the SQL Server transport, take a look in your SQL database, where NServiceBus has created each of the queues listed above as a separate table.

Summary

In this lesson we created a simple messaging endpoint to make sure it works. In the next lesson, we'll define a message, a message handler, and then send the message and watch it get processed.

Next Lesson: Sending a command


Last modified