Blocking request/response with Netty

Tomasz Blachowicz tblachowicz at gmail.com
Wed Jul 22 12:57:59 EDT 2009


Hi Trustin,


Trustin Lee wrote:
> 
> In HTTP, the first response corresponds to the first request and the
> second response corresponds to the second response and so on.
> Therefore, you could maintain a queue of sent requests, and poll the
> request from the queue when you receive a response.  Then you can match
> a request and response.
> 

This is all right. However I'm not too sure how you'd implement the matching
of requests and responses. I played a little with Netty recently and managed
to implement synchronous call on client side, that works pretty well. Here
is how I have done that. Can you have a look and comment on my approach? I
wonder if there are any other idioms/patterns to implement synchronous call
using Netty.

Please, bear in mind that I still want to use single instance of client by
many threads. Effectively single channel being used by many threads. Do you
thing it is correct approach?

Let's assume that we are having the interface of synchronous service
(client):

<code>
public interface SyncService {
  Response callService(Request request);
}
</code>

It doesn't matter what is Request and Response and how these are serialized
and transported to the server and back.

Here is how I implemented the interface:

<code>
@ChannelPipelineCoverage("one")
public class SyncServiceImpl extends SimpleChannleUpstreamHAndler implements
SyncService, Closeable {

  private final Lock lock = new ReentrantLock();
  private final Queue<Callback> callbacks = new
ConcurrentLinkedQueue<Callback>();

  private Channel channel;

  public Response callService(Request request) {
    Callback callback = new Callback(); 
    lock.lock();
    try {
      callbacks.add(callback);
      channel.write(request);	
    } finally {
      lock.unlock();
    }
    return callback.get();
  }

  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
    Response response = (Response) e.getMessage();
    callbacks.poll().handle(response);
  }
	
  public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
    channel = e.getChannel();
    super.channelOpen(ctx, e);
  }

  public void close() throws IOException {
    channel.close().awaitUninterruptibly();
  }

  static class Callback {

    private final CountDownLatch latch = new CountDownLatch(1);

    private Response response;

    Response get() {
      try {
        latch.await();
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
      return response;
    }

    void handle(Response response) {
      this.response = response;
      latch.countDown();
    }
  }

}
</code>

How does it look to you? Any ideas how to improve this?

Thanks a lot for any help and piece of discussion!

Regards,
Tom


-- 
View this message in context: http://n2.nabble.com/Blocking-request-response-with-Netty-tp3254813p3304504.html
Sent from the Netty User Group mailing list archive at Nabble.com.


More information about the netty-users mailing list