users@grizzly.java.net

Re: Threading and invocation of Filter.handleXXX methods

From: Matthew Swift <matthew.swift_at_oracle.com>
Date: Wed, 13 Oct 2010 18:40:46 +0200

  Thanks Alexey for the clear response. I agree that it is not a good
idea to perform blocking operations in filter chains and that we should
hand these tasks off to a separate thread pool.

Cheers!

:-)

Matt


> Hi Matt,
>
>> Basically, in my dumb proxy example, it listens for incoming client
>> connections and, on connect, it creates an associated connection
>> between the proxy and the remote server. I am creating the connection
>> synchronously from within the Filter.handleAccept(FilterChainContext)
>> method. Unfortunately my example self-deadlocks because the
>> handleAccept method is being invoked by a SelectorRunner and the
>> Future that is returned from the connection attempt can never be
>> closed, because the selector needs to run in order to close it (on my
>> machine there is only one SelectorRunner by default).
> Ok.
>
>> I'm surprised by this because if I change the implementation a bit so
>> that connections are lazily created during invocation of a subsequent
>> Filter.handleRead event then everything works ok, simply because
>> there are more worker threads than selectors.
> Understand.
>
>
>> Of course, this approach is still flawed and a self-deadlock is still
>> possible. E.g. if there are N Grizzly worker threads and each
>> performs N synchronous IO operations then there will be no worker
>> threads available to service the IO events and close the Futures. The
>> correct approach, I assume (correct me if I am wrong) is to hand-off
>> work like this to a separate worker thread pool and leave Grizzly
>> selectors/workers to service just the IO events.
>>
>> However, I do find this behavior surprising. I imagined that all
>> handleXXX methods would be processed by Grizzly worker threads. Is it
>> expected?
> It may vary, depending on IOStrategy you may chose
> (transport.setStrategy()):
>
> WorkerThreadStrategy (default one) uses worker threads to execute I/O
> events, except CONNECT and ACCEPT events (the intent was to make
> ACCEPT, CONNECT more optimal, but may be we should change it to be
> consistent for all)
> If you'll chose SameThreadStrategy *all* the I/O events in a
> FilterChain will be processed by Selector threads. This strategy might
> be optimal for non-blocking usecases.
>
> In general, IMO it would be good to not use blocking operations inside
> the filterchains. Here is the sample code you might want to use for
> handleAccept operation [1]
>
> Thanks.
>
> WBR,
> Alexey.
>
> [1]
> @Override
> public NextAction handleAccept(final FilterChainContext ctx)
> throws IOException {
> final Connection connection = ctx.getConnection();
>
> final TCPNIOTransport transport =
> (TCPNIOTransport) connection.getTransport();
>
> final SocketConnectorHandler connectorHandler =
> new TCPNIOConnectorHandler(transport);
>
> connectorHandler.setProcessor(redirectChain);
>
> connectorHandler.connect(new InetSocketAddress(redirectHost,
> redirectPort),
> new EmptyCompletionHandler<Connection>() {
>
> @Override
> public void completed(Connection peerConnection) {
> AttrUtil.setPeer(connection, peerConnection);
> AttrUtil.setPeer(peerConnection, connection);
> resume();
> }
>
> @Override
> public void failed(Throwable throwable) {
> try {
> connection.close();
> } catch (IOException ignored) {
> }
>
> resume();
> }
>
> private void resume() {
> ctx.setFilterIdx(ctx.getFilterIdx() + 1);
> ctx.resume();
> }
> });
>
> return ctx.getSuspendAction();
> }
>
>>
>> Cheers,
>>
>> Matt
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>