Tuesday, December 18, 2007

Java NIO and The Grizzly

I have been working on a small side project to develop a highly scalable reporting and analysis service. Part of the design calls for all "processing" nodes to maintain persistent connections to every other "processing" node in the cloud. I knew the idea of using blocking IO and the 1:1 thread/connection model was going to be horrible for this design.

I first turned to the Java NIO packages. I always start with trying to understand the underlying technology before I start looking into libraries. While I wouldn't say that the Java NIO packages are exceptionally difficult to work with, they leave a lot to be desired in the documentation department. Even the examples and tutorials that exist on the internet appear incomplete. Very few touch on the best methods for dealing with write operations. Between writes, and fully understanding how to properly iterate over my selected key set (you have to call iterator.remove() after calling iterator.next()), I spent a week trying to get a firm grasp on what was really going on. By the end of the second week, I had created a prototype java application that listened on sockets and was playing hot potato with a serializable java object. I had acquired my basic understanding. Now ready for looking into libraries.

Grizzly is the library I am currently looking at. Getting a simple echo service up and running in Grizzly is a no brainer. The concept can be completed in under 20 lines of code. Grizzly even comes with protocol parsers and other useful interfaces that make developing your own protocol directly on-top of TCP or UDP a straightforward exercise.  I haven't gotten to far down the path of implementation yet, but I will definately be using Grizzly rather than rolling my own NIO solution.

The code for the Grizzly version of a simple echoing server is below:
public static void main(String[] args) 
throws IOException {
Controller controller = new Controller();
TCPSelectorHandler handler =
new TCPSelectorHandler();
handler.setPort(9090);
controller.setProtocolChainInstanceHandler(
new DefaultProtocolChainInstanceHandler() {
public ProtocolChain poll() {
ProtocolChain chain = protocolChains.poll();
if (chain == null) {
chain = new DefaultProtocolChain();
chain.addFilter(new ReadFilter());
chain.addFilter(new EchoFilter());
}
return chain;
}
}
);
controller.addSelectorHandler(handler);
controller.start();
}

I also researched the following libraries: EmberIO (part of Pyrasun), Apache Mina, and Coconut AIO. I will be posting some of my experiences with these libraries later.