Friday, May 11, 2012

Time To Consider Node.js?

Unless you’ve been living under a rock for the past couple of years, you’ll have heard the buzz about Node.js, a platform for building network applications in Javascript. If, like me, you’re a .NET developer working on Windows, you’ll have thought, ‘that’s nice, now back to work’. But I think it’s now time to consider adopting Node as a core part of our toolkit. It allows us to do some things far easier than we can with our existing tools, and it’s now mature enough on Windows that you don’t have to jump through hoops in order to use it. There’s a very nice IIS integration story now with iisnode.

Here’s a little example. I needed to write a little web service that simply waited for a second before responding. I wanted a harness to test the asynchronous IO handling in EasyNetQ. I’d written something to do this in .NET previously. Here’s my IHttpHandler implementation…

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace TestHttpHandler
{
public class TimerHandler : IHttpAsyncHandler
{
public void ProcessRequest(HttpContext context)
{
throw new InvalidOperationException("This handler cannot be called synchronously");
}

public bool IsReusable
{
get { return false; }
}

public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback callback, object state)
{
var taskCompletionSouce = new TaskCompletionSource<bool>(state);
var task = taskCompletionSouce.Task;

var timer = new Timer(timerState =>
{
context.Response.Write("OK");
callback(task);
taskCompletionSouce.SetResult(true);
});
timer.Change(1000, Timeout.Infinite);

return task;
}

public void EndProcessRequest(IAsyncResult result)
{
// nothing to do
}
}
}

It’s not trivial to write a non-blocking server like this. You have to have a good handle on the TPL and APM, something that’s beyond many mid-level .NET developers. In order to run this on a server I have to set up a new Web Application in IIS and configure the Web.config file. OK, it’s not a huge amount of work, but it’s still friction for a small throw-away experiment.
 
Here’s the same thing in Node:
var http = require('http');

http.createServer(function (req, res) {
setTimeout(function () {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('OK');
}, 1000);
}).listen(1338);

console.log('LongRunningServer is at http://localhost:1338/');

First of all, it’s less lines of  code. Node is asynchronous out of the box, you don’t have to understand anything more than standard Javascript programming idioms in order to write this service. I’m a total Node novice, but I was able to put this together far faster than the .NET example above.

But the runtime story is very nice too. Once I’ve installed Node (which is now just a question of running the Windows installer) all I have to do is open a command prompt and write:

node LongRunningServer.js

I don’t think I’m going to abandon .NET just yet, but I do think that I’ll be considering Node solutions as an integral part of my .NET applications.

Wednesday, May 09, 2012

EasyNetQ: A Breaking Change, IPublishChannel

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:

bus.Publish(message);

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())
{
publishChannel.Publish(message);
}

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!

Monday, May 07, 2012

The Configuration Complexity Clock

When I was a young coder, just starting out in the big scary world of enterprise software, an older, far more experienced chap gave me a stern warning about hard coding values in my software. “They will have to change at some point, and you don’t want to recompile and redeploy your application just to change the VAT tax rate.” I took this advice to heart and soon every value that my application needed was loaded from a huge .ini file. I still think it’s good advice, but be warned, like most things in software, it’s good advice up to a point. Beyond that point lies pain.

Let me introduce you to my ‘Configuration Complexity Clock’.

ConfigurationComplexityClock

This clock tells a story. We start at midnight, 12 o’clock, with a simple new requirement which we quickly code up as a little application. It’s not expected to last very long, just a stop-gap in some larger strategic scheme, so we’ve hard-coded all the application’s values. Months pass, the application becomes widely used, but there’s a problem, some of the business values change, so we find ourselves rebuilding and re-deploying it just to change a few numbers. This is obviously wrong. The solution is simple, we’ll move those values out into a configuration file, maybe some appsettings in our App.config. Now we’re at 2 on the clock.

Time passes and our application is now somewhat entrenched in our organisation. The business continues to evolve and as it does, more values are moved to our configuration file. Now appsettings are no longer sufficient, we have groups of values and hierarchies of values. If we’re good, by now we will have moved our configuration into a dedicated XML schema that gets de-serialized into a configuration model. If we’re not so good we might have shoe-horned repeated and multi-dimensional values into some strange tilda and pipe separated strings. Now we’re at 4 or 5 on the clock.

More time passes, the irritating ‘chief software architect’ has been sacked and our little application is now core to our organisation. The business rules become more complex and so does our configuration. In fact there’s now a considerable learning curve before a new hire can successfully carry out a deployment. One of our new hires is a very clever chap, he’s seen this situation before. “What we need is a business rules engine” he declares. Now this looks promising. The configuration moves from its XML file into a database and has its own specialised GUI. Initially there was hope that non-technical business users would be able to use the GUI to configure the application, but that turned out to be a false hope; the mapping of business rules into the engine requires a level of expertise that only some members of the development team possess. We’re now at 6 on the clock.

Frustratingly there are still some business requirements that can’t be configured using the new rules engine. Some logical conditions simply aren’t configurable using its GUI, and so the application has to be re-coded and re-deployed for some scenarios. Help is at hand, someone on the team reads Ayende’s DSLs book. Yes, a DSL will allow us to write arbitrarily complex rules and solve all our problems. The team stops work for several months to implement the DSL. It’s a considerable technical accomplishment when it’s completed and everyone takes a well earned break. Surely this will mean the end of arbitrary hard-coded business logic? It’s now 9am on the clock.

Amazingly it works. Several months go by without any changes being needed in the core application. The team spend most of their time writing code in the new DSL. After some embarrassing episodes, they now go through a complete release cycle before deploying any new DSL code. The DSL text files are version controlled and each release goes through regression testing before being deployed. Debugging the DSL code is difficult, there’s little tooling support, they simply don’t have the resources to build an IDE or a ReSharper for their new little language. As the DSL code gets more complex they also start to miss being able to write object-oriented software. Some of the team have started to work on a unit testing framework in their spare time.

In the pub after work someone quips, “we’re back where we started four years ago, hard coding everything, except now in a much crappier language.”

They’ve gone around the clock and are back at 12.

Why tell this story? To be honest, I’ve never seen an organisation go all the way around the clock, but I’ve seen plenty that have got to 5, 6, or 7 and feel considerable pain. My point is this:

At a certain level of complexity, hard-coding a solution may be the least evil option.

You already have a general purpose programming language, before you go down the route of building a business rules engine or a DSL, or even if your configuration passes a certain level of complexity, consider that with a slicker build-test-deploy cycle, it might be far simpler just to hard code it.

As you go clockwise around the clock, the technical implementation becomes successively more complex. Building a good  rules engine is hard, writing a DSL is harder still. Each extra hour you travel clockwise will lead to more complex software with more bugs and a harder learning curve for any new hires. The more complex the configuration, the more control and testing it will need before deployment. Soon enough you’ll find that there’s little difference in the length of time it takes between changing a line of code and changing a line of configuration. Rather than a commonly available skill, such as coding C#, you find that your organisation relies on a very rare skill: understanding your rules engine or DSL.

I’m not saying that it’s never appropriate to implement complex configuration, a rules-engine or a DSL, Indeed I would jump at the chance of building a DSL given the right requirements, but I am saying that you should understand the implications and recognise where you are on the clock before you go down that route.

Friday, May 04, 2012

How Do I Detect When A Client Thread Exits? Make The Client Tell You.

Yesterday I asked the LazyWeb for some help: how does library code detect then a client thread that has called one of its methods exits? There followed a very useful discussion on Stack Overflow. I’ve been persuaded by Martin James’ arguments that however one tries to do it, there will always be scenarios where the result won’t be optimal. The answer is for the client to tell the library explicitly when it’s finished its work.

“'it just works' solutions just don't <g>. Whidows, Linux, every OS I've ever used has a 'token', 'handle' or other such object as the solution to maintaining state across calls. Using inplicit thread-local data and polling for thread termination etc. will suck the life out of your library”

OK, so I  buy the argument, but what’s the best way to change the API so that the client can indicate that it’s finished its work?

First alternative.

Provide a method that returns a worker that implements IDisposable and make it clear in the documentation that you should not share workers between threads. Here's the modified library:

public class Library
{
public LibraryWorker GetLibraryWorker()
{
return new LibraryWorker();
}
}

public class LibraryWorker : IDisposable
{
public void StartSomething()
{
Console.WriteLine("Library says: StartSomething called");
}

public void Dispose()
{
Console.WriteLine("Library says: I can clean up");
}
}

The client is now a little more complicated:

public class Client
{
private readonly Library library;

public Client(Library library)
{
this.library = library;
}

public void DoWorkInAThread()
{
var thread = new Thread(() =>
{
using(var worker = library.GetLibraryWorker())
{
worker.StartSomething();
Console.WriteLine("Client thread says: I'm done");
}
});
thread.Start();
}
}

The main problem with this change is that it's a breaking change for the API. Existing clients will have to be re-written. Now that's not such a bad thing, it would mean revisiting them and making sure they are cleaning up correctly.

Non-breaking second alternative.

The API provides a way for the client to declare 'work scope'. Once the scope completes, the library can clean up. The library provides a WorkScope that implements IDisposable, but unlike the first alternative above, the StartSomething method stays on the Library class:

public class Library
{
public WorkScope GetWorkScope()
{
return new WorkScope();
}

public void StartSomething()
{
Console.WriteLine("Library says: StartSomething called");
}
}

public class WorkScope : IDisposable
{
public void Dispose()
{
Console.WriteLine("Library says: I can clean up");
}
}

The client simply puts the StartSomething call in a WorkScope...

public class Client
{
private readonly Library library;

public Client(Library library)
{
this.library = library;
}

public void DoWorkInAThread()
{
var thread = new Thread(() =>
{
using(library.GetWorkScope())
{
library.StartSomething();
Console.WriteLine("Client thread says: I'm done");
}
});
thread.Start();
}
}

I like this less than the first alternative because it doesn't force the library user to think about scope. What do you think?

Thursday, May 03, 2012

Help! How Do I Detect When a Client Thread Exits?

Here’s an interesting library writer’s dilemma. In my library (in my case EasyNetQ) I’m assigning thread local resources. So when a client creates a new thread and then calls certain methods on my library new resources get created. In the case of EasyNetQ a new channel to the RabbitMQ server is created when the client calls ‘Publish’ on a new thread. I want to be able to detect when the client thread exits so that I can clean up the resources (channels).

The only way of doing this I’ve come up with is to create a new ‘watcher’ thread that simply blocks on a Join call to the client thread. Here a simple demonstration:

First my ‘library’. It grabs the client thread and then creates a new thread which blocks on ‘Join’:

public class Library
{
public void StartSomething()
{
Console.WriteLine("Library says: StartSomething called");

var clientThread = Thread.CurrentThread;
var exitMonitorThread = new Thread(() =>
{
clientThread.Join();
Console.WriteLine("Libaray says: Client thread existed");
});

exitMonitorThread.Start();
}
}

Here’s a client that uses my library. It creates a new thread and then calls my library’s StartSomething method:

public class Client
{
private readonly Library library;

public Client(Library library)
{
this.library = library;
}

public void DoWorkInAThread()
{
var thread = new Thread(() =>
{
library.StartSomething();
Thread.Sleep(10);
Console.WriteLine("Client thread says: I'm done");
});
thread.Start();
}
}

When I run the client like this:

var client = new Client(new Library());

client.DoWorkInAThread();

// give the client thread time to complete
Thread.Sleep(100);

I get this output:

Library says: StartSomething called
Client thread says: I'm done
Libaray says: Client thread existed

The thing is, I really don’t like the idea of all these blocked watcher threads hanging around. Is there a better way of doing this?

EasyNetQ: Topic Based Routing

EasyNetQ is my simple .NET API for RabbitMQ. I’ve just added a new feature, Topic based routing. It’s very cool.

Topic based routing is a RabbitMQ feature that allows a subscriber to filter messages based on multiple criteria. A topic is a list of words delimited by dots that are published along with the message. Examples would be, "stock.usd.nyse" or "book.uk.london" or "a.b.c", the words can be anything you like, but would usually be some attributes of the message. The topic string has a limit of 255 characters.

To publish with a topic, simply use the overloaded Publish method:

bus.Publish("X.A", message);

Subscribers can filter messages by specifying a topic to match to. These can include the wildcard characters:

* (star) to match to exactly one word.

# (hash) to match to zero or more words.

So a message that is published with the topic "X.A.2" would match "#", "X.#", "*.A.*" but not "X.B.*" or "A". To subscribe with a topic, use the overloaded Subscribe method:

bus.Subscribe("my_id", "X.*", handler);

A warning. Two separate subscriptions with the same subscriberId but different topic strings probably will not have the effect you are expecting. A subscriberId effectively identifies an individual AMQP queue. Two subscribers with the same subscriptionId will both connect to the same queue and both will add their own topic. So, for example, if you do this:

bus.Subscribe("my_id", "X.*", handler);
bus.Subscribe("my_id", "*.B", handler);

Each handler will be round-robbin’d with any messages that match "X.*" or "*.B".

Now, if you want to match on multiple topics ("X.*" OR "*.B") you can use another overload of the Subscribe method that takes multiple topics, like this:

bus.Subscribe("my_id", new[]{"X.*", "*.B"}, handler);

There are topic overloads for the SubscribeAsync method that work in exactly the same way.