jsr340-experts@servlet-spec.java.net

[jsr340-experts] Re: HTTP/2 Push Was: Server-Sent Events in Java EE 8

From: Greg Wilkins <gregw_at_intalio.com>
Date: Tue, 24 Jun 2014 21:57:07 +0200

On 20 June 2014 22:25, <edward.burns_at_oracle.com> wrote:

> GW> Jetty is has now implemented http2
>
> As it currently stands! In any case congratulations. I was hoping we
> could have a clean slate with HTTP/2 and make it so it is 100%
> non-blocking. Is that the approach you took in Jetty?
>

Yes in its current state (draft 12). I'm not a huge fan many aspects of
http2, but we felt that there was enough determination to progress on the
current basis, so we can better contribute feedback if we are an
implementer rather than just a commentator.

Jetty has been pretty much fully non-blocking for some time now. We
convert async IO to blocking IO only in the ServletOutputStream level with
a BlockingCallback class.

(plus we have habitually clean slated our IO layer every few years for the
last 20 years! yes Jetty is 20 years old this December!).


>
> GW> and we are about to start experimenting with push APIs. If anybody
> GW> has some thoughts on what this should look like, we are keen to try
> GW> ideas out.
>
> Did you expose the request/response multiplexing capabilities to users
> of your API? What about stream priority?
>

The multiplexing should be hidden. Each multiplexed stream represents a
single request response so from a servlet point of view it should be hard
to tell the difference between 2 request delivered over the same HTTP/2
connection vs 2 delivered over 2 HTTP/1.0 connections.

Stream priority is not a certainty to be included in the spec. But if it
is, it is probably more driven from the client side as the individual
renderers will decide what resource they really need next to draw the page
as fast as possible. There is some scope for the server to second guess
this with initial push priorities, but I think it will be very client
dependent so not a great need to expose it.



> GW> The rough idea that I have had (without too much deep though), is
> GW> that push could be added to the RequestDispatcher mechanism. The
> GW> way push works in HTTP/2 is that a response to a request may
> include
> GW> notification via push promises of simulated request to which the
> GW> server will soon send the response to. To model this in the server
> GW> we could just add a push method to the request dispatcher, so that
>
> GW>
> request.getRequestDispatcher("/some/resource").push(request,priority);
>
> My ideas for this are still very sketchy, but I know I'd rather see
> push
> fall out of the design as a consequence of having an API that more
> closely models the fact that HTTP/2 gives us the capability of multiple
> simultaneous streams within one connection, each of which is composed
> of
> bi-directional messages.
>
>
Well I think streams should mostly be hidden. However pushed resources
will have a close relationship to the initial request. The way it will
work is as follows:

   1. The client will send a single request, typically for /index.html or
   similar
   2. The server will work out what resources are associated with
   /index.html and send push promises to the client in the response stream for
   the original request.
   3. Each push promise will contain a simulated request that the server is
   saying that it will respond to. The simulated request will have things
   like user-agent and cookies that are most likely based off the initial
   request.
   4. The server will start sending each pushed response in some order
   (potentially serially?)
   5. The client will send priorities and/or resets to control the exact
   order and which resources actually get pushed.


So the push API will need:

   - a response stream that is being sent to the server, preferably before
   any/much content has been committed and the client started requesting
   referenced resources.
   - a prototype request on which to base the push promise.
   - the URI of the resource to push

This kind of looks like a request dispatcher as you obtain one with the new
URI and then pass in a request and response. RequestDispatcher can even be
obtained during init and then used over and over for multiple
push(request,response)'s

> In other words, having push just be an offshoot from RequestDispatcher
> seems overly limiting. I wonder if something closer to
> javax.websocket.Session is a better abstraction?
>

The mechanism is a lot more restricted that websocket, hence a restricted
API is called for.

Note that eventually http/2 framing should also carry websocket and/or
similar, in which case a different API will be called for (hopefully just
jsr356)

cheers

PS. note that for SPDY, jetty hides the push mechanism from the servlet and
just builds a resource relationship map using referrer fields. These are
pushed behind the scenes. Having push in the API would allow this kind of
cache to be moved to a filter.

-- 
Greg Wilkins <gregw_at_intalio.com>
http://eclipse.org/jetty HTTP, SPDY, Websocket server and client that scales
http://www.webtide.com  advice and support for jetty and cometd.