Blocking request/response with Netty

Tomasz Blachowicz tblachowicz at gmail.com
Wed Jul 22 18:38:29 EDT 2009


Hey Iain,

Thanks a lot for your reply. Blocking while waiting for asynchronous
response to arrive is what I precisely wanted to do. I don't want to wait
until the frame is send to the wire, this is just a half of the story and
honestly speaking not the more interesting half ;)

If I'm reading your recommended approach right this is something that I
presented in my previous post in sample code. I reckon there is however a
gap in this what you are saying. Here is the thing, the setup of a response
listener and writing to channel must be synchronized. Otherwise there is a
potential situation when the listener may be notified in wrong order. This
is why I used ReentrantLock to make sure that registering the listener in a
queue and asynchronous writing to channel happens together.

Anyone else, any other patterns or idioms?

Cheers,
Tom


Iain McGinniss wrote:
> 
> The complication in this case is that waiting on the success of the  
> ChannelFuture for write isn't enough - Tomasz also needs to wait for  
> the response corresponding to the request in the write. The situation  
> is potentially further complicated by whether the client wishes to use  
> HTTP pipelining or not. If pipelining is used, it simplifies the  
> ChannelHandlers that need to be written as they just fire stuff out  
> onto the wire without waiting for responses. If pipelining is not  
> used, you need to wait for each response to come back before you can  
> send another request.
> 
> I would recommend first implementing the asynchronous solution -  
> dispatch an HttpRequest to Netty, and store an event listener in a  
> FIFO queue corresponding to this request. As responses come back in,  
> pop a listener off the queue and notify it that the response has  
> arrived, attaching the HttpResponse object. Wrapping that in a  
> synchronous call is then quite simple - create a new CountdownLatch  
> for each request (with value 1), send the request using the  
> asynchronous interface and give it an event listener that will call  
> countDown() on the latch. Then, call await() on the latch without a  
> timeout if you like. Edge cases exist, for instance of the connection  
> dies before the response comes back you should notify all listeners.
> 
> Iain
> 
> On 22 Jul 2009, at 18:19, Michael McGrady wrote:
> 
>> Just a thought.  While Netty is asynchronous, synchronicity is always
>> just virtual anyway, cf. TCP/IP.  You can build a program using the
>> ChannelFuture functionality to create your own virtual synchronicity.
>> 'Hope this helps.
>>
>> How did you implement a Netty synchronous call on the client side?  I
>> assume that you mean a virtual synchronous call?  Netty is inherently
>> asynchronous.
>>
>> Mike
>>
>>
>> On Jul 22, 2009, at 9:57 AM, Tomasz Blachowicz wrote:
>>
>>>
>>> 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-tp3254813p3306337.html
Sent from the Netty User Group mailing list archive at Nabble.com.


More information about the netty-users mailing list