How TopShelf solves a specific problem very elegantly.

A lot of our architecture is based on windows services. One of the issues with this setup is that we would have to install those windows services on our developer machines. Something we are not really fond of, especially since they won't be used for the bigger part of our work. We just want to run the services related to the specific problem we are trying to solve.

To work around this inconvenience, we would create a project containing some general code and next to that project there is a console application project and a windows service project. You can imagine that this causes a lot of overhead in the solution. For each service we would have three projects instead of only the one we actually need. I have seen this approach before and one more than one occasion, and was never really a big fan of it.

But now we have a more elegant solution. It's name is TopShelf.

How to use TopShelf

I won't explain all  the details. It's definitely worth reading the documentation at http://topshelf-project.com/.
What you will read here is a brief description of how we use it.

Creating a new project

The project we create is a 'console application' where Program is our startup object. My apologies for the nasty black marking (using Snipping Tool and I rather don't mention too much internal details).

Where to get TopShelf?

We get TopShelf from Nuget. Simply use the 'Package Manager UI' or run the following command in the 'Package Manager Console':

Install-Package Topshelf -Version 3.1.1

Creating the service

Before telling you how host your services using the Topshelf Hosting Framework we have to create the service.
The service looks like this.

namespace <YOURNAMESPACE>
{
    public class Service
    {
        public Service()            
        { 
        }

        public void Start()
        {
             /* DO WORK HERE */
        }

        public void Stop()
        {
            /* DO CLEANUP HERE */
        }
    }
}

It's important to properly dispose of objects you created or threads you have started when calling Stop(). On more than one occasion we write multithreaded services and if we don't cleanup threads nicely in this phase, we might get sharing violations when we try to copy over a new version of the service.

Hosting the service

The final thing we need to do is the actual hosting of this service using TopShelf. This happens in the Program.cs file.

using Topshelf;

namespace <YOURNAMESPACE>
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
            HostFactory.Run(x =>
            {
                x.Service<Service>(s =>
                {
                    s.ConstructUsing(() =>
                    {
                        Bootstrapper.Run();
                        return new Service();
                    });
                    s.WhenStarted(tc => tc.Start());
                    s.WhenStopped(tc => tc.Stop());
                });

                x.SetDisplayName("<YOUR SERVICE DISPLAY NAME>");
                x.SetServiceName("<YOUR SERVICE NAME>");
                x.SetDescription("<YOUR SERVICE DESCRIPTION>");

                // Service Identity

                x.RunAsLocalSystem();

                // Advanced Settings

                //// Specifies that the service supports the shutdown service command, allowing the services control manager to quickly shutdown the service.
                x.EnableShutdown();

                // Service recovery plan
                x.EnableServiceRecovery(rc =>
                {
                    rc.RestartService(1); // restart the service after 1 minute
                });
            });
        }
    }
}

It's very important that you run all initialization logic for your service in the ConstructUsing block. Running it outside of the Topshelf initialization might lead to unexpected behavior.
Our initialization happens in a Bootstrapper static class. So this is called first thing when entering the ConstructUsing method.

All other options are described either in code, and a lot more can be found on the TopShelf documentation site.

And the result is what exactly?

As a developer we can simply debug the console application. No windows service is installed. When working on a specific issue we can run the services by running their console variant. On our servers we can copy the bin output and by running a simple command the service is installed and configured. No more need to create a service installation file.

"Path to your.exe" install

Other calls we often make are 'stop' and 'start'. This is very handy stuff when you integrate this in your continuous delivery story.

Installing RabbitMQ on Windows

A brief post on how to install RabbitMQ on your Windows server.

Install Erlang

Erlang is a programming language used to build massively scalable soft real-time systems with requirements on high availability. Some of its uses are in telecoms, banking, e-commerce, computer telephony and instant messaging. Erlang's runtime system has built-in support for concurrency, distribution and fault tolerance.

http://www.erlang.org/

  1. Download the binary for your system.
    There are 32 bit and 64 bit binaries available.
  2. Copy the binary to the server (if you haven't downloaded it directly from the server of course) and run it.
  3. Choose components, Documentation is not required and can be unchecked.

  4. Choose installation location, default installation should be ok.

  5. Choose the start menu location.

  6. When you continue and choose 'Install' Visual C++ 2010 components will be installed.
    Go ahead and install them.

  7. Once this is done, Erlang installation continues and should finish successfully.
  8. Remote the setup binary from your system.

 Erlang is installed and is running. We can now install RabbitMQ.

 

Install RabbitMQ

RabbitMQ provides robust messaging for applications. It is easy to use and runs on all major operation systems. It supports a huge number of developer platforms, is open source and commercially supported.

http://www.rabbitmq.com/

  1.  Download the windows binary.
  2. Choose the components to install.

  3. Choose the installation location.

  4. The installation completes.
  5. Don't forget to remove the setup binary (I just like my servers clean).

Installing the RabbitMQ Management Plugin

By default you can manage your rabbitmq installation using the command prompt. There is an other option and that is the Administration plugin which provides an HTTP-based API for management and monitoring your RabbitMQ installation, along with a browser-based UI and a command line tool.

http://www.rabbitmq.com/management.html

  1. Start a RabbitMQ commandprompt.
    This should be available through the start menu.

  2. The command to install the management plugin is:
    rabbitmq-plugins enable rabbitmq_management
    The result should ask you to restart the RabbitMQ for changes to take effect.

  3. Restart RabbitMQ as asked. Advised way is to stop and start the RabbitMQ service.
    Either through the ‘windows services’-snapin, or using the RabbitMQ options in the start menu.

 

You can now browse to your RabbitMQ administration page by pointing the browser's url to:
http://<server-name>:15672 where 15672 is the default port.

The default username is 'guest' and the default password is 'guest'.

Congratulations, you have now installed RabbitMQ and can investigate the administration options in detail.

 

 

 

Why we use MassTransit

A couple of months ago we were challenged to refactor one of our domains. I won't discuss all the reasons we had to refactor this, but the main reason might have been the degree of high coupling. Fortunately there are pretty solid solutions available to easily evolve to loose coupled systems. To achieve loose coupling we wanted to introduce a MessageBus and a PubSub architecture. Well defined events would be published and any service interested would subscribe to those events. That's just a brief summary of what happens, but I don't want to bore anyone.

In the beginning there was NServiceBus

Because I am familiar with NServiceBus, we created a first POC using NServiceBus 4. We had a basic setup in no time. That is what NServiceBus promises and they didn't fail to deliver there. After some initial demos and finetuning some processes we had the feeling we were on the right track and this would eventually go into production. Going into production means you have to respect licenses. This was the first time NServiceBus let me down. The licensing calculation is not sufficiently transparent (that's an absolute personal opinion; as is everything else on the blog) and repeatedly contacting NServiceBus didn't really provide a solution for us. We needed a go-live license, but for the initial release, we rather didn't spend any money until the entire setup proved itself worthy. Note: I respect Udi Dahan's (NServiceBus) position.

During this entire period I was aware of the existence of MassTransit. In the past I had already told myself to look into it and give it a fair chance. It just didn't happen, but now I was triggered.

So why end up with MassTransit?

I rewrote this paragraph a couple of times. It seems I always start explaining what we did to solve the technical issues we experienced introducing MassTransit. I'll blog about this later (that's a promise). SPOILER ALERT: all issues where gracefully resolved and more.

Turned out we have multiple reasons to remove all NServiceBus logic and switch to MassTransit,

Was it all about money?

No, it was not. However it is fair to say that since MassTransit is free to use, it's absolutely a very good reason to make the switch. We would all be lying if we say we don't care about the dollars. You could discuss there is also the cost of ownership which would be lower using NServiceBus. That might be true, but MassTransit isn't an untested MessageBus by far.

Great, fast feedback, reactive and proactive

What I mean is that whenever we were stuck, we had multiple ways to get unblocked very fast. First of all there is the documentation. True, it requires some additions and lacks a well documented example. Using the Google group and Twitter we always got our answers in no time. It's amazing to what 160 characters worth of text might lead. We got into contact with Chris Patterson (MassTransit) who obviously was of great help and if you shoot a tweet to #mtproj, you will be helped.

Potential, potential, potential

Looking at the MassTransit codebase I see a clean codebase. Easy to understand, easy to extend. There might not be a reason to extend a lot, but to give you another heads up: we added direct messaging to MassTransit through configuration. Those familiar with NServiceBus, will relate to this as the UnicastBus.

To sum it all up, we are using a professional grade MessageBus and we feel backed by a great community. The fact that it is free to use only adds up to the pleasure of using MassTransit.
Stay tuned for a more technical blogpost. I am sure you'll get something out of it.