On 05/22/2013 11:20 AM, Mark Thomas wrote:
>
> I was getting close the the point where I was going to have some time to
> work on this so I have been mulling it over some more. My conclusion is
> that auto-blocking isn't going to solve the current "can't implement
> WebSocket 1.0 on Servlet 3.1" problem.
>
> The issue is not the writes in the WebSocket API that explicitly block -
> auto-blocking should work for those. (Or rather, I can't see any reason
> why it wouldn't work right now.)
>
> The current sticking point is the non-blocking writes that return a
> Future. Consider the following sequence:
>
> - Container receives WebSocket message
> - Container thread triggers onMessage processing in app
> - app (still on container thread) sends a message in response using the
> Future style
> - app calls Future.get()
>
> At this point the container thread (A) is blocked inside Future.get().
> Since this is in the WebSocket implementation the Servlet implementation
> has no knowledge that the thread is blocked. Unblocking thread A
> requires a second container thread to call onWritePossible().
Ok, you're right. I agree, in this scenario, it will be an async write
for the Servlet API, with no means to send the event while the container
thread is blocked. IMO this sort of flexibility is useless (I would
think it was reasonable to ask of the user to decide if a write should
be blocking or not when doing it ...), but at this point it doesn't
matter ...
>
> Auto-blocking doesn't help here because the WebSocket implementation
> doesn't know that the write is effectively going to be blocking until
> after the write has been initiated.
>
> At the moment, my current solution of allowing a maximum of one read
> thread (i.e. in response to the socket signalling it has data to read)
> and one write thread (i.e. in response to the socket signalling it is
> ready to receive data) per request rather than a maximum of one thread
> per request looks like the best option.
Ok, that's reasonable. The whole use case (mixing async and blocking)
doesn't make sense for regular Servlets. But relaxed concurrency would
be acceptable after a connection is upgraded, since there is no access
to the non synced Servlet API objects (which turns out to be a very good
design choice). Ultimately, it is desirable, once upgraded, to be able
to do any sort of IO, so allowing one write + one read concurrency could
be a good solution then.
I would like to keep the strict one container thread rule for Servlets
though, since none of the Servlet container objects are synced.
>
> Other options I have considered:
> 1 Change the non-blocking aspects of the API in Servlet 3.1 to use the
> same style as WebSocket.
>
> 2 Expose the object being used for the one thread per request lock
> through the Servlet API so the WebSocket API can use it rather than
> its own lock to implement blocking. This could enable the Servlet API
> to detect when a container thread was blocked and therefore allow
> another thread to do some work on the same request.
>
> 3 Give up and use some the container internals directly.
>
> I assume that option 1 is a non-starter.
Yes, it doesn't seem very useful in Servlets.
>
> Option 2 exposes a very low level object. Users would *really* need to
> know what they were doing to use it. Because it is so low level
> different containers are going to have taken very different approaches.
> Finding a common API that works for all - without significant effort for
> some - could be tricky.
>
> I really, really don't want to do 3.
>
> Thoughts? Comments?
>
Rémy