Search |
|||
Rémi Forax's blogNIO server with continuation in JavaPosted by forax on November 22, 2009 at 6:13 AM PST
Java VM embodies continuations now (not in production, in a hacking mode :), This post shows how to write a non-blocking server with continuations. Why using continuation with non blocking IO There are two models when you deals with IO:
JDK 7 also provides classes to use asynchronous IOs instead of Selector but you can't used them with continuations at least those implemented in the VM. The asynchronous callback of an asynchronous read/write can be called in another thread and continuations implemented in the VM are restricted to one thread (if yield occurs in one thread, resume must be called by the same thread). * Remember that in hotspot (like most Java VMs) the stack is one preallocated array (so a big contiguous blob of memory) and not a linked list of stack frames like in stackless Python.** This model has nothing to do with threadless but I'm a big fan of these t-shirts. *** It's a weak criticism because I have no idea how to do better. The big advantage of using continuations in this context is that you can code as if you were using threads, i.e in a blocking IO style, but the runtime will use non-blocking IO under the hood. Continuation with NIO Here is an example of an echo server using non blocking IO and continuation, if you want another service, create a class that extends AbstractNIOServer and overrides method handle of the request processor, don't forget to tag it with annotation @Continuable. A request processor is an object that will be created to handle one connection of one client, it creates and manage the underlying continuation.
public class EchoNIOServer extends AbstractNIOServer {
@Override
protected RequestProcessor createProcessor(Selector selector, SocketChannel channel) {
return new RequestProcessor(selector, channel) {
@Override
@Continuable
protected void handle(ByteBuffer buffer) throws IOException {
while (read(buffer) != -1) {
buffer.flip();
write(buffer);
if (buffer.hasRemaining())
buffer.compact();
else
buffer.clear();
}
close();
}
};
}
public static void main(String[] args) throws IOException {
new EchoNIOServer().start();
}
}
As you notice, it's a simple while loop that read data and write the same data. The code is as you will write it if you use blocking IO. Under the hood
When the server receive a new connection, it first accept it
and then delegate to a thread the processing of the request,
this is done by posting the client channel in a queue
and wake up the selector of one worker thread.
Then the worker thread executes the last part of the above snippet,
it allocates a new byte buffer, creates a request processor
and starts a fiber that executes the
method handle of the RequestProcessor.
[...]
for(;;) {
int select = selector.select();
if (select != 0) {
for(Iterator
The whole code is available here.
What's next This webserver is a toy, there is lots of rooms of improvement (use more than one thread to do the accept, pipeline the write, pool buffers and fibers, etc.) I haven't benchmark this implementation because I have no gigabit switch available to do it. If you test it, don't forget to drop me a comment on this post. By the way, don't forget to increase the number of threads in AbstractNIOServer.
See you (*) soon, * With google analytics, this is almost true. »
Related Topics >>
Glassfish J2EE J2SE Java Enterprise Open JDK Programming Virtual Machine Web Applications Comments
Comments are listed in date ascending order (oldest first)
|
CategoriesArchivesNovember 2009
October 2009 September 2009 August 2009 July 2009 June 2009 May 2009 April 2009 February 2009 January 2009 December 2008 November 2008 October 2008 September 2008 July 2008 May 2008 April 2008 March 2008 February 2008 January 2008 November 2007 October 2007 September 2007 August 2007 July 2007 June 2007 May 2007 March 2007 February 2007 January 2007 December 2006 November 2006 October 2006 September 2006 August 2006 July 2006 Recent Entries |
||
|
|