Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[jetty-dev] HttpInput refactor for Servlet 3.1



All,

I'm just going to type-out-loud for a bit regarding the refactor of HttpInput to support the servlet 3.1 asynchronous read mechanism.  If anybody has any thoughts... specially the SPDY guys, just jump in and say.


Currently HttpInput<T> is implemented as an extension of ServletInputStream that has the key additional method of

    public void content(T item)

Which delivers new content to the stream. For the HTTP implementation, T is simply a ByteBuffer referring to content parsed from the HTTP connection buffer.  For SPDY, T is a DataInfo which represents an entire data frame received on the MUX stream for the HttpChannel.

HttpInput is implemented internally as an ArrayQueue<T> with a call to content adding an item to the queue.   But note that the queue is not a blocking queue and wakeup of any blocking reader is performed by a call from content(T) to onContentQueued.

The reason that a blocking queue is not used is that the way read consumes the queue is a little complex.  Specifically read peeks at the head of the queue and uses get(T item, byte[] buffer, int offset, int length) to consume content, which may not be all the content available in the item.  Only once the head item is empty of content is it actually popped off the queue.     Hence a full synchronise block is used to protect the Q and associated fields.

If the read finds that the Q is empty it calls blockForContent() to wait for content.  In the default implementation, this is just a lock().wait() and the onContentQueued(T) call does a lock().notify();       This works fine for SPDY where different threads are doing the parsing and calling the application - so that any thread blocked on a read in the application will not prevent additional parsing and thus calls to content(T).

For HTTP, the thread that does the parsing is the thread that is dispatched to the application and is thus likely to be the thread that is blocked in a read (but async threads may also call read and block).   Thus the simply wait/notify does not work for HTTP.  Instead HttpInput is extended by HttpConnection.Input and the blockForContent method is replaced so it is the application thread that calls read that is used to do additional parsing of any raw content read on the connection.   To do this, the HTTP implementation must call a combination of:

  fillInterested(_readBlocker);_readBlocker.block();  - to block until a read is possible
  getEndPoint().fill(_requestBuffer); - to get raw bytes
  _parser.parseNext(_requestBuffer); - to parse the bytes

Thus the onContentQueued(T) impl for HTTP is changed to an empty method as no wakeup is needed since the reading thread is woken up already to do the IO and parsing.      The normal HttpConnection.onFillable() method is not used to process content as it is called by a dispatched thread.  The onFillable(_readBlocker) utilises the selector thread to do the wakeup, so no extra dispatch is needed.

So what do we need to change?  Basically we need to make read be able to switch to a non blocking mode, so that if no bytes are available it will return zero bytes and then if isReady() is called a callback to a ReadListener is done in a context anointed thread. This bit is a pain as the HttpInput has no idea of context and may be used for one context for one request and another context for the next!  This is the hardest nut to crack here.

I also think that we need to change the implementation to stop trying to make one impl mostly work for SPDY and HTTP.  So I think we need to have separate derivations of HttpInput that provide the different block/wakeup mechanisms for HTTP and SPDY. 
SPDY and maybe able to use a more efficient blocking queue.

anyway - I hope to make some progress this week and this is really the final part of 3.1 we need to implement before starting to do some beta releases of 9.1

cheers





--
Greg Wilkins <gregw@xxxxxxxxxxx>
http://www.webtide.com
Developer advice and support from the Jetty & CometD experts.
Intalio, the modern way to build business applications.

Back to the top