dev@grizzly.java.net

Re: [Fwd: grizzly versus mina]

From: Robert Greig <robert.j.greig_at_gmail.com>
Date: Sat, 26 May 2007 16:40:44 +0100

On 25/05/07, Jeanfrancois Arcand <Jeanfrancois.Arcand_at_sun.com> wrote:

> In Grizzly, we initialize at startup a pool of temporary Selector. Those
> Selectors are available for read/write. As an example, I frequently use
> temporary Selectors when handling the http protocol. With HTTP, it is is
> difficult to detect the end of the stream. One way to handle the problem
> is by parsing the message, getting the content-length and try to read
> bytes until you reach the content-length value. This approach (which is
> what MINA does...at least last time I've looked) is to register the
> SelectionKey back to the main Selector, cache/persist the ByteBuffer
> until all the bytes are read. Since most of the time the Selector is not
> running on the same thread (WorkerThread) as the class that parse the
> bytes, the cost of switching the thread can be expensive. Hence instead
> this approach, you stay on the WorkerThread and when no more bytes are
> available (sochetChannel.read returns 0), you register the channel to a
> temporary Selector and try to read from it. Most of the time you will be
> able to read the extra bytes. See [1] for more info.

Interesting. You avoid a context switch but if I understand correctly
it does mean you cannot read and parse in parallel. With MINA, the
socket io processor just does a select, then reads as much as it can
off the socket (up to a limit which works ok with AMQP since there is
a negotiated limit of each frame) and does this constantly in a loop.
The worker thread pool grabs data from a per connection queue, and
starts decoding. However by the time it has decoded and decided that
it needs some more bytes, the socket io processor will have put
another byte buffer onto the per connection queue of bytes. The worker
thread will immediately grab that buffer and process it. (We do have
some fairness heuristics built in to avoid starvation if there is a
constant stream of bytes flowing in).

> >> There's some additional variations one can incorporate too
> >> such as ... distributed network applications tend to be bursty, for that
> >> reason you might consider adding to the definition "expecting more data"
> >> the notion of waiting a few more seconds before considering the overall
> >> read event being done.
> >
> > Do you build anything in to ensure fairness/avoid starvation?
>
> The timeout you set on the temporary Selector.select() is quite
> important. Why, because if all WorkerThread are blocked because no bytes
> are available, then you hit a DOS style attack.

Is a form of DOS style attack not still possible in the sense that
malicious clients could bring the performance of the server right down
depending on timeout you choose?

> BTW the cometd sub project [2] is a kind of message bus. I've already
> looked at Qpid to see if I can use it under the hood. I'm swamped those
> day but this is something I would like to explore :-)

That would be really interesting. I'll take a look at cometd. If you
have any questions about Qpid just let me know.

RG