Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[jetty-dev] Jetty-9 development

All,

Recently, we've been doing a bit too much of our development behind
"closed doors" within webtide/intalio.    Now that we've started
jetty-9 development, I'd like to reverse that trend and start having
more of the development discussions on the open forums (as we used to
do, and should have all along).
There is a jetty-9 branch already, but it is a long long way from
being usable... or even compileable!  But if you want to follow the
discussions, the code is there.

So why are we having jetty-9?  have we just gone jetty-8?  Is there
need for another major version change?

The driver for another new version is the increasing use of new
protocols on the web, namely Websocket and SPDY.  We have supported
both of those in the 7/8 architecture, but it has been a bit of a
stretch.   The way that jetty currently works is as follows:

+ we have our own Buffer and EndPoint abstraction, which roughly
corresponds to NIO2's AsynchronousSocketChannel and is an asynchronous
end point. We had our own abstraction so we could support JVMs that
did not support NIO.  NIO is pretty much universal now, so we can
definitely drop having our own buffers, and might even be able to move
away from our own EndPoint abstraction.

+ Connectors are responsible for accepting new EndPoints and turning
then into Connection, with the primary connection implementations
being AsyncHttpConnection and BlockingHttpConnection, but now also
SpdyConnection and WebSocketConnection.   In a world where even smart
phones are multi-threaded and NIO, I don't think the blocking
connection style needs to be supported anymore and we can move to all
Async.  We no longer have to run on palm pilots!

+ The primary entry point for Connections, is the method :
Connection handle()  . Which does the parsing of the requests, calls
the Server.handle(request,response) and then completes the generation
of the response.   Note that it return a Connection, so that
HttpConnection.handle() call can return a WebSocketConnection when an
upgrade request is received.    Also SSL now is implemented as an
Connection interceptor, so you can upgrade the chain of
EndPoint->HttpConnection    to
EndPoint->SslConnection->HttpConnection   and then to
EndPoint->SslConnection->WebSocketConnection.

So far so good.   Except things are becoming even more complex, mostly
because of mutliplexing over Websocket and SPDY. Currently 1
Connection instance == 1 TCP Socket == 1 protocol instances == 1
application channels (eg stream of HTTP requests or
WebSocketMessages).  But websockets will soon have a MUX extension
that will allow multiple websocket streams to be transported over the
one TCP connection,  thus  1 TCP Socket == 1 protocol instance == N
application channels.   This is already the case with SPDY which
supports multiple channels, each with HTTP semantics over the one TCP
Connection.  With Spdy we have:    1TCP Socket == 1 SPDY connection
instance == N Fake HTTP connection instances == N application
channels.   This is implemented today with
EndPoint->SslConnection->SpdyConnection->SpdyHttpConnection->app

But it is getting even more complex, as SPDY is also able to transport
WebSockets (at least the semantics of websocket, but not the
protocol), so we will need to be able to have
EndPoint->SslConnection->SpdyConnection->[SpdyHttpConnection|SpdyWebSocketConnection]->app

We are working towards this architecture, but currently in 7/8 it
means that we have to fake HTTP connections and have mock parsers.
Which is working.... but is not an elegant solution long term.

So what we need to do in jetty-9 is to separate out the wire protocol
handling from the application protocol handling.    So you can have:

 HTTP wire protocol -> 1 HTTP application protocol
 Websocket wire protocol -> 1 Websocket application protocol
 Websocket wire protocol -> N Websocket application protocol
 SPDY wire protocol ->  N HTTP application protocol + M Websocket
application protocol

Ideally the application protocol handlers will be able to be written
so that they are independent over the wire protocol they are being
used on.

So where is the jetty-9 branch?

The jetty-util, jetty-io and jetty-http modules have all been worked
over to remove the old jetty Buffer abstraction and to use NIO
directly.  The HTTP parser and generator have also been re factored to
be independent of the IO, so they can be used with jetty EndPoints or
JDK7 NIO2 Channels etc.  These build and pass there tests and have had
a lot of cruft from 15 years of development removed (I'm not saying
there is not more cruft to be removed).

jetty-server is where the current development is being done.  The
AsyncHttpConnection class has been torn apart into a HttpConnection
and HttpChannel class, representing the wire protocol and the
application protocol.   So parsers/generators are in HttpConnection,
while requests, responses and continuations are in the HttpChannel.
 The current challenge is to find the write contract between these
classes so that it may be efficiently generalised so the HttpChannel
will work with a future SpdyConnection and that we'll be able to have
a WebSocketConnection and a WebSocketChannel, with the later being
usable with a SpdyConnection.   It is an open question how much (if
any) behaviour will end up in an AbstractConnection and
AbstractChannel.  This split is complicated by the fact that we are
trying to change to the new parser/generator style at the same time.

Another complication is that the split also means a move away from
Jetty's single entry point for a connection.   Currently every things
starts with a call to Connection.handle(), even if you wake up a
suspended continuation the request is redispatched via a called to
Connection.handle(), which means that there can be a nice safe finally
block in Connection.handle() that will eventually see the request exit
in a non suspended state and thus know to complete the response and
move onto parsing the next request.      But if we are split between
HttpConnection and HttpChannel, things like resuming a suspended
request are not IO events, so they have no business being dispatched
via HttpConnection.handle(), instead they will probably be a direct
dispatch to HttpChannel.handle().     This in turn means that when
HttpChannel knows the request/response cycle is complete, it will have
to call back to the HttpConnection to complete the response.   THIS IS
A BIG CHANGE, because it means that instead of the same thread doing
the complete in a finally block, the complete will be triggered by a
call from a thread that may be entirely different from the one that
called HttpConnection.handle().    Thus we have to make the code
thread safe in areas that we have not had to before (although async
servlets are already pushing us this way a bit and so is SPDY muxed
channels).

It also makes upgrade a bit more complex.  Currently we essentially do:

 Connection connection = new HttpConnection(...)
 while(notdone)
    connection=connection.handle();

This will become:

 Connection connection = new HttpConnection(...)
 while(notdone)
    connection=connection.handle()
    {
        Channel nc = _channel.handle();
        if (_channel!=nc)
            return newConnectionFor(nc);
        return this;
   }

Anyway, that's enough brain farting for one email.  Just wanted to
explain some of the jetty-9 commits that you might have seen go by.
The stable branches remain 7/8 and they will continue to be developed
and improved for some time.  I hope 9 will be ready before Servlet 3.1
is out.... but we will see.
All/any feedback comments etc are welcome.

regards


Back to the top