Microservice Architectures in .NET

This guide series covers rapid prototyping of Windows Services using Top Shelf to host the service and the newest version of Mass-Transit 3 to connect to the service bus.

The modest requirements

Prerequistes

If you aren’t familiar with messaging and workers, or pub/sub architecture in general, check out the RabbitMQ tutorial page. RabbitMQ can be installed using Chocolatey via
PS> choco install rabbitmq

Getting Started

If you still have Visual Studio Express (Why?) it doesn’t include any templates for Windows services, although if you’ve downloaded the for Desktop version you should be able to create a Console application, and that’s all we need. The core required .NET namespaces are all still available, but you’re honestly better off upgrading to the latest Community Edition.

Open up Visual Studio and create a New Project. Start with a Console Application, and give it a name. In this demo I’ll be using ChirpBot. Next you’ll want to install a few packages from Nuget. Open your Package Manager console and type the following commands:

PM> Install-Package MassTransit -pre  
PM> Install-Package TopShelf  

This should install TopShelf, MassTransit and all it’s dependencies. The newest version has Courier and a Host built right in.

TopShelf at your Service

TopShelf is a wrapper for Windows Service Framework that simplifies creation, configuration, and installation of a new service into the Service Control Manager. If you’ve ever worked with Windows Services before, this is a big dealâ„¢. It also abstracts out all the annoying quirks and gotchas, making life easier for everyone.

The first thing you need to do is pop off a new class that inherets from Topshelf.ServiceControl

class Chirper : Topshelf.ServiceControl {  
    private readonly System.Timers.Timer _timer;
    public Chirper() {
        _timer = new System.Timers.Timer(1000) {AutoReset = true};
        _timer.Elapsed += (sender, eventArgs) => NewChirp();
    }

    private void NewChirp() { 
        Console.WriteLine("Chirping at {0}", DateTime.Now.ToString("T")); 
    }
    public bool Start(HostControl hostControl) { _timer.Start(); return true; }
    public bool Stop(HostControl hostControl) { _timer.Stop(); return true; }
}

By inheriting from ServiceControl we get bit of boilerplate functionality, including the Start and Stop functions. Your service class doesn’t have to have a dependency on TopShelf, but then you have to manually bind the Start and Stop handlers and it changes the syntax of the next step significantly.

One note is we’re using System.Timers.Timer instead of System.Threading.Timer because it’s simpler to start and stop. There are ways around this (Timeout.Infinite) but it requires specifying your timeouts every time in the Start function. This may or may not be advantageous, depending on your setup.

Now that we have our worker class, it’s time to tie it in to the TopShelf HostFactory. Hop back over to your Main() loop and add the following code:

static void Main(){  
    var host = Topshelf.HostFactory.New(x => {
        x.Service<Chirper>();
        x.RunAsLocalService();
    });
    host.Run();
}

What’s happening here? We’re firing off the Topshelf Host Factory to create a new service host. We’re passing in our Chirper class as the default service and telling it to run as a LocalService. Many times you’ll want to run as a NetworkService for a single deployment if you need advanced network access, like binding a listener to use OWIN Self Host to provide your service with an API (keep an eye out for a post on this in the future). In an enterprise environment you can have your installer pass explicit service account credentials to the service setup on the command line.

That’s it?

Yup, TopShelf handles the rest. Hit F5 and you’ll run a console program that writes to the command line every 1000ms. Wonderful! Want to install it as a service? Navigate your favorite shell to the /bin/Debug directory and run the following:

PS> .\ChirpBot.exe install --sudo  

The --sudo flag prompts for UAC so you don’t have to worry about running as an administrator from the command line. Uninstalling is just as easy:

PS> .\ChirpBot.exe uninstall --sudo  

Want to view the service in the Windows Service Manager? (Win+R > services.msc) And to start and stop the service from the command line use the following:

PS> .\ChirpBot.exe start  
PS> .\ChirpBot.exe stop  

Get on the bus!

Okay, so we’ve got our Windows Service. You said something about messaging? Yup! Stay tuned for Part 2!

Source Code

All the source code for this series can be found on Github. If you have any questions, please leave a comment.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.