You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@hc.apache.org by David Koski <da...@mac.com> on 2007/07/12 23:10:09 UTC

async http clients

Hi,

I have been reading NHttpClient and I think I finally understand how  
it all works, but I am a bit stuck with how to use it.  Let's say I  
wanted to build something along the lines of a load balancer:  many  
incoming connections, many outgoing connections, most are idle or  
waiting for a response.

Focusing on the outgoing connections part, I want to have keep-alive  
connections to a set of hosts, multiple connections per port.  For  
example:

	LB -> host1:80
	LB -> host1:80
	LB -> host1:80

	LB -> host2:80
	LB -> host2:80

If I have a queue of operations I want to do, I can see how I might  
use a series of ioReactor.connect() calls to create the connections  
and have submitRequest() methods in my HttpRequestExecutionHandler  
pull them off the queue and service them.

The problem I am having is dealing with the steady state.  I would  
like to keep these connections around for a while (and indeed using  
the DefaultConnectionReuseStrategy they are kept alive.  However, once  
my queue drains and my submitRequest() method returns null, how do I  
wake the handlers back up?  I can see any way to get the reactor to  
call back into my handler without opening a new connection.

Am I missing something?  Or going about this the wrong way?

Thanks,
David Koski

---------------------------------------------------------------------
To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: httpcomponents-dev-help@jakarta.apache.org


Re: Re: async http clients

Posted by da...@mac.com.
Hi,

This is on OS X 10.4.8 using a rather old JDK (upgrading that is maybe difficult).  I tried the following variations:

- Oleg's changes in revision 614701

- -Djava.nio.preferSelect=true

- a very hacky workaround (to see if it worked) where I had the BaseIOReactor service a set of connections that want to wake up during its execute() method

I was unable to reproduce my hang with either the preferSelect or the hacky thing I did, but I did still see the same hang with the changes in 614701.

I can't easily upgrade the JDK on these machines, but other desktop machines running OSX 10.5.1 with 10.5.0_13 are unable to reproduce the problem.  So old JDK + kqueue maybe bad.

Thanks,
David Koski

-- Sam Berlin wrote : 
There were definitely bugs with AbstractSelector & SelectionKeys that
could cause deadlocks to happen in rare scenarios.  See
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4744057 for one.
Newer versions of the JDK have fixed this.  There were also problems
on OS X if using the default selector (kqueue) that caused the entire
system to hang.  I'm not positive if newer releases have fixed this,
as we switched to not using kqueue (-Djava.nio.preferSelect=true).

Sam


--
This message was sent on behalf of david_koski@mac.com at openSubscriber.com
http://www.opensubscriber.com/message/dev@hc.apache.org/8447337.html

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Re: async http clients

Posted by Sam Berlin <sb...@gmail.com>.
There were definitely bugs with AbstractSelector & SelectionKeys that
could cause deadlocks to happen in rare scenarios.  See
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4744057 for one.
Newer versions of the JDK have fixed this.  There were also problems
on OS X if using the default selector (kqueue) that caused the entire
system to hang.  I'm not positive if newer releases have fixed this,
as we switched to not using kqueue (-Djava.nio.preferSelect=true).

Sam

On 1/23/08, Oleg Kalnichevski <ol...@apache.org> wrote:
>
> On Tue, 2008-01-22 at 22:23 -0800, David Koski wrote:
> > Hi,
> >
> > Sadly, I can't claim I have personal knowledge of this being true.  I
> > have an application where I can get a reactor thread to hang like that
> > and this description seemed to fit.  I have been unable to make a unit
> > test that reproduces this behavior however.
> >
> > I am using:
> >
> > java version "1.5.0_06"
> > Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-113)
> > Java HotSpot(TM) Server VM (build 1.5.0_06-68, mixed mode)
> >
> > Here is another reference:
> >
> >       http://forum.java.sun.com/thread.jspa?threadID=459338&start=120
> >
> > "register and interestOps will block if they are done from another
> > thread while the select is active. That's why I use a list of things
> > that must be done in the select loop."
> >
> > And I read this:
> >
> >       http://java.sun.com/j2se/1.5.0/docs/api/java/nio/channels/SelectionKey.html
> >
> > Selection keys are safe for use by multiple concurrent threads. **The
> > operations of reading and writing the interest set will, in general,
> > be synchronized with certain operations of the selector. Exactly how
> > this synchronization is performed is implementation-dependent: In a
> > naive implementation, reading or writing the interest set may block
> > indefinitely if a selection operation is already in progress**; in a
> > high-performance implementation, reading or writing the interest set
> > may block briefly, if at all. In any case, a selection operation will
> > always use the interest-set value that was current at the moment that
> > the operation began.
> >
>
> The key here is the word 'naive'. I have a hard time believing Sun chose
> a naive implementation for its JREs. Inability to modify interest
> operations on the selection key from a different thread _utterly_
> defeats its purpose.
>
> NIO used to be (and still is) quite buggy. So, before I start working on
> an ugly workaround I would like to be reasonably sure this is not a bug
> in Sun's older JREs. I would also like to know to what extent different
> platforms are affected. The JRE you are using is fairly out of date.
> Could you please upgrade to the latest Java 1.5 release (1.5.0_14) and
> see if the problem is still reproducible? Have you tried Java 1.6? What
> OS are you on?
>
> Oleg
>
> > To me, that suggests that select + modify of the interest ops == bad,
> > which agrees with what the various posts say.  Again, I have no nio
> > expertise, so my idea may be bunk.
> >
> > David Koski
> >
> >
> > On Jan 22, 2008, at 2:22 PM, Oleg Kalnichevski wrote:
> >
> > >
> > > On Tue, 2008-01-22 at 16:52 -0500, david_koski@mac.com wrote:
> > >> Hi,
> > >>
> > >> Your suggestion worked well, but I think I ran into a problem with
> > >> it (using A6, if it matters).  I ended up with a hung IOReactor
> > >> thread:
> > >>
> > >> Thread [I/O dispatcher 2] (Suspended)
> > >>    KQueueArrayWrapper.register0(int, int, int, int) line: not
> > >> available [native method]
> > >>    KQueueArrayWrapper.setInterest(int, int) line: 99
> > >>    KQueueSelectorImpl.putEventOps(SelectionKeyImpl, int) line: 179
> > >>    SocketChannelImpl.translateAndSetInterestOps(int,
> > >> SelectionKeyImpl) line: 733
> > >>    SelectionKeyImpl.nioInterestOps(int) line: 87
> > >>    SelectionKeyImpl.interestOps(int) line: 65
> > >>    IOSessionImpl.clearEvent(int) line: 125
> > >>    AsyncHTTPClient
> > >> $
> > >> AsyncConnection
> > >> (DefaultNHttpClientConnection).produceOutput(NHttpClientHandler)
> > >> line: 183
> > >>    AsyncHTTPClient
> > >> $EventDispatch(DefaultClientIOEventDispatch).outputReady(IOSession)
> > >> line: 102
> > >>    AsyncHTTPClient$EventDispatch.outputReady(IOSession) line: 353
> > >>    BaseIOReactor.writable(SelectionKey) line: 109
> > >>    BaseIOReactor(AbstractIOReactor).processEvent(SelectionKey) line:
> > >> 192
> > >>    BaseIOReactor(AbstractIOReactor).processEvents(Set) line: 174
> > >>    BaseIOReactor(AbstractIOReactor).execute() line: 137
> > >>    BaseIOReactor.execute(IOEventDispatch) line: 69
> > >>    AbstractMultiworkerIOReactor$Worker.run() line: 281
> > >>    Thread.run() line: 613
> > >>
> > >> The AsyncHTTPClient class is mine, but it is just very thin
> > >> wrappers on the default implementations.  Anyway, the thread hangs
> > >> like this while trying to clear the write interest on the
> > >> SelectionKey.  I only seem to run into this at high (> 1000 per
> > >> second) request rates.
> > >>
> > >> I think this may actually be related to waking up the the IOControl:
> > >>
> > >>                conn.requestOutput();
> > >>
> > >> this ends up here:
> > >>
> > >>
> > >>    public void setEvent(int op) {
> > >>        if (this.status == CLOSED) {
> > >>            return;
> > >>        }
> > >>        synchronized (this.key) {
> > >>            int ops = this.key.interestOps();
> > >>            this.key.interestOps(ops | op);
> > >>            this.key.selector().wakeup();
> > >>        }
> > >>    }
> > >>
> > >> However, several sites suggest that concurrent modification of
> > >> SelectionKeys is a recipe for disaster:
> > >>
> > >> http://rox-xmlrpc.sourceforge.net/niotut/index.html
> > >>
> > >> As a result, if you plan to hang onto your sanity don't modify the
> > >> selector from any thread other than the selecting thread. This
> > >> includes modifying the interest ops set for a selection key,
> > >> registering new channels with the selector, and cancelling existing
> > >> channels.
> > >>
> > >>
> > >>
> > >> But that is _exactly_ what I am doing here.  The thread that wants
> > >> the connection is touching the SelectionKey and the IOReactor (I/O
> > >> dispatcher) thread is also touching it.
> > >>
> > >> Am I understanding this correctly?
> > >>
> > >
> > > David,
> > >
> > > The javadocs of the SelectonKey clearly states the class is threading
> > > safe [1]:
> > >
> > > "... Selection keys are safe for use by multiple concurrent
> > > threads..."
> > >
> > > One certainly should not attempt to access the selector from multiple
> > > threads but it is completely new to me some people think this also
> > > applies to the selection keys. Selection keys would be completely
> > > pointless if they were not threading safe
> > >
> > > Can this be a JRE issue? What is the JRE you are using?
> > >
> > > Oleg
> > >
> > > [1]
> > > http://java.sun.com/j2se/1.4.2/docs/api/java/nio/channels/SelectionKey.html
> > >
> > >
> > >> Thanks,
> > >> David Koski
> > >>
> > >>
> > >> -- Oleg Kalnichevski wrote :
> > >> On Thu, 2007-07-12 at 14:10 -0700, David Koski wrote:
> > >>> Hi,
> > >>>
> > >>> I have been reading NHttpClient and I think I finally understand how
> > >>> it all works, but I am a bit stuck with how to use it.  Let's say I
> > >>> wanted to build something along the lines of a load balancer:  many
> > >>> incoming connections, many outgoing connections, most are idle or
> > >>> waiting for a response.
> > >>>
> > >>> Focusing on the outgoing connections part, I want to have keep-alive
> > >>> connections to a set of hosts, multiple connections per port.  For
> > >>> example:
> > >>>
> > >>>   LB -> host1:80
> > >>>   LB -> host1:80
> > >>>   LB -> host1:80
> > >>>
> > >>>   LB -> host2:80
> > >>>   LB -> host2:80
> > >>>
> > >>> If I have a queue of operations I want to do, I can see how I might
> > >>> use a series of ioReactor.connect() calls to create the connections
> > >>> and have submitRequest() methods in my HttpRequestExecutionHandler
> > >>> pull them off the queue and service them.
> > >>>
> > >>> The problem I am having is dealing with the steady state.  I would
> > >>> like to keep these connections around for a while (and indeed using
> > >>> the DefaultConnectionReuseStrategy they are kept alive.  However,
> > >>> once
> > >>> my queue drains and my submitRequest() method returns null, how do I
> > >>> wake the handlers back up?  I can see any way to get the reactor to
> > >>> call back into my handler without opening a new connection.
> > >>>
> > >>> Am I missing something?  Or going about this the wrong way?
> > >>>
> > >>
> > >> Hi David
> > >>
> > >> Just invoke IOControl#requestOutput() (implemented by all NHttp
> > >> connections) and it will cause the I/O reactor to fire up the
> > >> NHttpClientHandler#requestReady() event, which you can use to
> > >> submit a
> > >> new request on that connection
> > >>
> > >> Hope this helps
> > >>
> > >> Oleg
> > >>
> > >>> Thanks,
> > >>> David Koski
> > >>>
> > >>> ---------------------------------------------------------------------
> > >>> To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jaka...
> > >>> For additional commands, e-mail: httpcomponents-dev-help@jaka...
> > >>>
> > >>>
> > >>
> > >>
> > >> ---------------------------------------------------------------------
> > >> To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jaka...
> > >> For additional commands, e-mail: httpcomponents-dev-help@jaka...
> > >>
> > >>
> > >> --
> > >> This message was sent on behalf of david_koski@mac.com at
> > >> openSubscriber.com
> > >> http://www.opensubscriber.com/message/httpcomponents-dev@jakarta.apache.org/7128633.html
> > >>
> > >> ---------------------------------------------------------------------
> > >> To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
> > >> For additional commands, e-mail: dev-help@hc.apache.org
> > >>
> > >>
> > >
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
> For additional commands, e-mail: dev-help@hc.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Re: async http clients

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Tue, 2008-01-22 at 22:23 -0800, David Koski wrote:
> Hi,
> 
> Sadly, I can't claim I have personal knowledge of this being true.  I  
> have an application where I can get a reactor thread to hang like that  
> and this description seemed to fit.  I have been unable to make a unit  
> test that reproduces this behavior however.
> 
> I am using:
> 
> java version "1.5.0_06"
> Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-113)
> Java HotSpot(TM) Server VM (build 1.5.0_06-68, mixed mode)
> 
> Here is another reference:
> 
> 	http://forum.java.sun.com/thread.jspa?threadID=459338&start=120
> 
> "register and interestOps will block if they are done from another  
> thread while the select is active. That's why I use a list of things  
> that must be done in the select loop."
> 
> And I read this:
> 
> 	http://java.sun.com/j2se/1.5.0/docs/api/java/nio/channels/SelectionKey.html
> 
> Selection keys are safe for use by multiple concurrent threads. **The  
> operations of reading and writing the interest set will, in general,  
> be synchronized with certain operations of the selector. Exactly how  
> this synchronization is performed is implementation-dependent: In a  
> naive implementation, reading or writing the interest set may block  
> indefinitely if a selection operation is already in progress**; in a  
> high-performance implementation, reading or writing the interest set  
> may block briefly, if at all. In any case, a selection operation will  
> always use the interest-set value that was current at the moment that  
> the operation began.
> 

The key here is the word 'naive'. I have a hard time believing Sun chose
a naive implementation for its JREs. Inability to modify interest
operations on the selection key from a different thread _utterly_
defeats its purpose.   

NIO used to be (and still is) quite buggy. So, before I start working on
an ugly workaround I would like to be reasonably sure this is not a bug
in Sun's older JREs. I would also like to know to what extent different
platforms are affected. The JRE you are using is fairly out of date.
Could you please upgrade to the latest Java 1.5 release (1.5.0_14) and
see if the problem is still reproducible? Have you tried Java 1.6? What
OS are you on?  

Oleg

> To me, that suggests that select + modify of the interest ops == bad,  
> which agrees with what the various posts say.  Again, I have no nio  
> expertise, so my idea may be bunk.
> 
> David Koski
> 
> 
> On Jan 22, 2008, at 2:22 PM, Oleg Kalnichevski wrote:
> 
> >
> > On Tue, 2008-01-22 at 16:52 -0500, david_koski@mac.com wrote:
> >> Hi,
> >>
> >> Your suggestion worked well, but I think I ran into a problem with  
> >> it (using A6, if it matters).  I ended up with a hung IOReactor  
> >> thread:
> >>
> >> Thread [I/O dispatcher 2] (Suspended)	
> >> 	KQueueArrayWrapper.register0(int, int, int, int) line: not  
> >> available [native method]	
> >> 	KQueueArrayWrapper.setInterest(int, int) line: 99	
> >> 	KQueueSelectorImpl.putEventOps(SelectionKeyImpl, int) line: 179	
> >> 	SocketChannelImpl.translateAndSetInterestOps(int,  
> >> SelectionKeyImpl) line: 733	
> >> 	SelectionKeyImpl.nioInterestOps(int) line: 87	
> >> 	SelectionKeyImpl.interestOps(int) line: 65	
> >> 	IOSessionImpl.clearEvent(int) line: 125	
> >> 	AsyncHTTPClient 
> >> $ 
> >> AsyncConnection 
> >> (DefaultNHttpClientConnection).produceOutput(NHttpClientHandler)  
> >> line: 183	
> >> 	AsyncHTTPClient 
> >> $EventDispatch(DefaultClientIOEventDispatch).outputReady(IOSession)  
> >> line: 102	
> >> 	AsyncHTTPClient$EventDispatch.outputReady(IOSession) line: 353	
> >> 	BaseIOReactor.writable(SelectionKey) line: 109	
> >> 	BaseIOReactor(AbstractIOReactor).processEvent(SelectionKey) line:  
> >> 192	
> >> 	BaseIOReactor(AbstractIOReactor).processEvents(Set) line: 174	
> >> 	BaseIOReactor(AbstractIOReactor).execute() line: 137	
> >> 	BaseIOReactor.execute(IOEventDispatch) line: 69	
> >> 	AbstractMultiworkerIOReactor$Worker.run() line: 281	
> >> 	Thread.run() line: 613	
> >>
> >> The AsyncHTTPClient class is mine, but it is just very thin  
> >> wrappers on the default implementations.  Anyway, the thread hangs  
> >> like this while trying to clear the write interest on the  
> >> SelectionKey.  I only seem to run into this at high (> 1000 per  
> >> second) request rates.
> >>
> >> I think this may actually be related to waking up the the IOControl:
> >>
> >>                conn.requestOutput();
> >>
> >> this ends up here:
> >>
> >>
> >>    public void setEvent(int op) {
> >>        if (this.status == CLOSED) {
> >>            return;
> >>        }
> >>        synchronized (this.key) {
> >>            int ops = this.key.interestOps();
> >>            this.key.interestOps(ops | op);
> >>            this.key.selector().wakeup();
> >>        }
> >>    }
> >>
> >> However, several sites suggest that concurrent modification of  
> >> SelectionKeys is a recipe for disaster:
> >>
> >> http://rox-xmlrpc.sourceforge.net/niotut/index.html
> >>
> >> As a result, if you plan to hang onto your sanity don't modify the  
> >> selector from any thread other than the selecting thread. This  
> >> includes modifying the interest ops set for a selection key,  
> >> registering new channels with the selector, and cancelling existing  
> >> channels.
> >>
> >>
> >>
> >> But that is _exactly_ what I am doing here.  The thread that wants  
> >> the connection is touching the SelectionKey and the IOReactor (I/O  
> >> dispatcher) thread is also touching it.
> >>
> >> Am I understanding this correctly?
> >>
> >
> > David,
> >
> > The javadocs of the SelectonKey clearly states the class is threading
> > safe [1]:
> >
> > "... Selection keys are safe for use by multiple concurrent  
> > threads..."
> >
> > One certainly should not attempt to access the selector from multiple
> > threads but it is completely new to me some people think this also
> > applies to the selection keys. Selection keys would be completely
> > pointless if they were not threading safe
> >
> > Can this be a JRE issue? What is the JRE you are using?
> >
> > Oleg
> >
> > [1]
> > http://java.sun.com/j2se/1.4.2/docs/api/java/nio/channels/SelectionKey.html
> >
> >
> >> Thanks,
> >> David Koski
> >>
> >>
> >> -- Oleg Kalnichevski wrote : 
> >> On Thu, 2007-07-12 at 14:10 -0700, David Koski wrote:
> >>> Hi,
> >>>
> >>> I have been reading NHttpClient and I think I finally understand how
> >>> it all works, but I am a bit stuck with how to use it.  Let's say I
> >>> wanted to build something along the lines of a load balancer:  many
> >>> incoming connections, many outgoing connections, most are idle or
> >>> waiting for a response.
> >>>
> >>> Focusing on the outgoing connections part, I want to have keep-alive
> >>> connections to a set of hosts, multiple connections per port.  For
> >>> example:
> >>>
> >>> 	LB -> host1:80
> >>> 	LB -> host1:80
> >>> 	LB -> host1:80
> >>>
> >>> 	LB -> host2:80
> >>> 	LB -> host2:80
> >>>
> >>> If I have a queue of operations I want to do, I can see how I might
> >>> use a series of ioReactor.connect() calls to create the connections
> >>> and have submitRequest() methods in my HttpRequestExecutionHandler
> >>> pull them off the queue and service them.
> >>>
> >>> The problem I am having is dealing with the steady state.  I would
> >>> like to keep these connections around for a while (and indeed using
> >>> the DefaultConnectionReuseStrategy they are kept alive.  However,  
> >>> once
> >>> my queue drains and my submitRequest() method returns null, how do I
> >>> wake the handlers back up?  I can see any way to get the reactor to
> >>> call back into my handler without opening a new connection.
> >>>
> >>> Am I missing something?  Or going about this the wrong way?
> >>>
> >>
> >> Hi David
> >>
> >> Just invoke IOControl#requestOutput() (implemented by all NHttp
> >> connections) and it will cause the I/O reactor to fire up the
> >> NHttpClientHandler#requestReady() event, which you can use to  
> >> submit a
> >> new request on that connection
> >>
> >> Hope this helps
> >>
> >> Oleg
> >>
> >>> Thanks,
> >>> David Koski
> >>>
> >>> ---------------------------------------------------------------------
> >>> To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jaka...
> >>> For additional commands, e-mail: httpcomponents-dev-help@jaka...
> >>>
> >>>
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jaka...
> >> For additional commands, e-mail: httpcomponents-dev-help@jaka...
> >>
> >>
> >> --
> >> This message was sent on behalf of david_koski@mac.com at  
> >> openSubscriber.com
> >> http://www.opensubscriber.com/message/httpcomponents-dev@jakarta.apache.org/7128633.html
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
> >> For additional commands, e-mail: dev-help@hc.apache.org
> >>
> >>
> >
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Re: async http clients

Posted by David Koski <da...@mac.com>.
Hi,

Sadly, I can't claim I have personal knowledge of this being true.  I  
have an application where I can get a reactor thread to hang like that  
and this description seemed to fit.  I have been unable to make a unit  
test that reproduces this behavior however.

I am using:

java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-113)
Java HotSpot(TM) Server VM (build 1.5.0_06-68, mixed mode)

Here is another reference:

	http://forum.java.sun.com/thread.jspa?threadID=459338&start=120

"register and interestOps will block if they are done from another  
thread while the select is active. That's why I use a list of things  
that must be done in the select loop."

And I read this:

	http://java.sun.com/j2se/1.5.0/docs/api/java/nio/channels/SelectionKey.html

Selection keys are safe for use by multiple concurrent threads. **The  
operations of reading and writing the interest set will, in general,  
be synchronized with certain operations of the selector. Exactly how  
this synchronization is performed is implementation-dependent: In a  
naive implementation, reading or writing the interest set may block  
indefinitely if a selection operation is already in progress**; in a  
high-performance implementation, reading or writing the interest set  
may block briefly, if at all. In any case, a selection operation will  
always use the interest-set value that was current at the moment that  
the operation began.

To me, that suggests that select + modify of the interest ops == bad,  
which agrees with what the various posts say.  Again, I have no nio  
expertise, so my idea may be bunk.

David Koski


On Jan 22, 2008, at 2:22 PM, Oleg Kalnichevski wrote:

>
> On Tue, 2008-01-22 at 16:52 -0500, david_koski@mac.com wrote:
>> Hi,
>>
>> Your suggestion worked well, but I think I ran into a problem with  
>> it (using A6, if it matters).  I ended up with a hung IOReactor  
>> thread:
>>
>> Thread [I/O dispatcher 2] (Suspended)	
>> 	KQueueArrayWrapper.register0(int, int, int, int) line: not  
>> available [native method]	
>> 	KQueueArrayWrapper.setInterest(int, int) line: 99	
>> 	KQueueSelectorImpl.putEventOps(SelectionKeyImpl, int) line: 179	
>> 	SocketChannelImpl.translateAndSetInterestOps(int,  
>> SelectionKeyImpl) line: 733	
>> 	SelectionKeyImpl.nioInterestOps(int) line: 87	
>> 	SelectionKeyImpl.interestOps(int) line: 65	
>> 	IOSessionImpl.clearEvent(int) line: 125	
>> 	AsyncHTTPClient 
>> $ 
>> AsyncConnection 
>> (DefaultNHttpClientConnection).produceOutput(NHttpClientHandler)  
>> line: 183	
>> 	AsyncHTTPClient 
>> $EventDispatch(DefaultClientIOEventDispatch).outputReady(IOSession)  
>> line: 102	
>> 	AsyncHTTPClient$EventDispatch.outputReady(IOSession) line: 353	
>> 	BaseIOReactor.writable(SelectionKey) line: 109	
>> 	BaseIOReactor(AbstractIOReactor).processEvent(SelectionKey) line:  
>> 192	
>> 	BaseIOReactor(AbstractIOReactor).processEvents(Set) line: 174	
>> 	BaseIOReactor(AbstractIOReactor).execute() line: 137	
>> 	BaseIOReactor.execute(IOEventDispatch) line: 69	
>> 	AbstractMultiworkerIOReactor$Worker.run() line: 281	
>> 	Thread.run() line: 613	
>>
>> The AsyncHTTPClient class is mine, but it is just very thin  
>> wrappers on the default implementations.  Anyway, the thread hangs  
>> like this while trying to clear the write interest on the  
>> SelectionKey.  I only seem to run into this at high (> 1000 per  
>> second) request rates.
>>
>> I think this may actually be related to waking up the the IOControl:
>>
>>                conn.requestOutput();
>>
>> this ends up here:
>>
>>
>>    public void setEvent(int op) {
>>        if (this.status == CLOSED) {
>>            return;
>>        }
>>        synchronized (this.key) {
>>            int ops = this.key.interestOps();
>>            this.key.interestOps(ops | op);
>>            this.key.selector().wakeup();
>>        }
>>    }
>>
>> However, several sites suggest that concurrent modification of  
>> SelectionKeys is a recipe for disaster:
>>
>> http://rox-xmlrpc.sourceforge.net/niotut/index.html
>>
>> As a result, if you plan to hang onto your sanity don't modify the  
>> selector from any thread other than the selecting thread. This  
>> includes modifying the interest ops set for a selection key,  
>> registering new channels with the selector, and cancelling existing  
>> channels.
>>
>>
>>
>> But that is _exactly_ what I am doing here.  The thread that wants  
>> the connection is touching the SelectionKey and the IOReactor (I/O  
>> dispatcher) thread is also touching it.
>>
>> Am I understanding this correctly?
>>
>
> David,
>
> The javadocs of the SelectonKey clearly states the class is threading
> safe [1]:
>
> "... Selection keys are safe for use by multiple concurrent  
> threads..."
>
> One certainly should not attempt to access the selector from multiple
> threads but it is completely new to me some people think this also
> applies to the selection keys. Selection keys would be completely
> pointless if they were not threading safe
>
> Can this be a JRE issue? What is the JRE you are using?
>
> Oleg
>
> [1]
> http://java.sun.com/j2se/1.4.2/docs/api/java/nio/channels/SelectionKey.html
>
>
>> Thanks,
>> David Koski
>>
>>
>> -- Oleg Kalnichevski wrote : 
>> On Thu, 2007-07-12 at 14:10 -0700, David Koski wrote:
>>> Hi,
>>>
>>> I have been reading NHttpClient and I think I finally understand how
>>> it all works, but I am a bit stuck with how to use it.  Let's say I
>>> wanted to build something along the lines of a load balancer:  many
>>> incoming connections, many outgoing connections, most are idle or
>>> waiting for a response.
>>>
>>> Focusing on the outgoing connections part, I want to have keep-alive
>>> connections to a set of hosts, multiple connections per port.  For
>>> example:
>>>
>>> 	LB -> host1:80
>>> 	LB -> host1:80
>>> 	LB -> host1:80
>>>
>>> 	LB -> host2:80
>>> 	LB -> host2:80
>>>
>>> If I have a queue of operations I want to do, I can see how I might
>>> use a series of ioReactor.connect() calls to create the connections
>>> and have submitRequest() methods in my HttpRequestExecutionHandler
>>> pull them off the queue and service them.
>>>
>>> The problem I am having is dealing with the steady state.  I would
>>> like to keep these connections around for a while (and indeed using
>>> the DefaultConnectionReuseStrategy they are kept alive.  However,  
>>> once
>>> my queue drains and my submitRequest() method returns null, how do I
>>> wake the handlers back up?  I can see any way to get the reactor to
>>> call back into my handler without opening a new connection.
>>>
>>> Am I missing something?  Or going about this the wrong way?
>>>
>>
>> Hi David
>>
>> Just invoke IOControl#requestOutput() (implemented by all NHttp
>> connections) and it will cause the I/O reactor to fire up the
>> NHttpClientHandler#requestReady() event, which you can use to  
>> submit a
>> new request on that connection
>>
>> Hope this helps
>>
>> Oleg
>>
>>> Thanks,
>>> David Koski
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jaka...
>>> For additional commands, e-mail: httpcomponents-dev-help@jaka...
>>>
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jaka...
>> For additional commands, e-mail: httpcomponents-dev-help@jaka...
>>
>>
>> --
>> This message was sent on behalf of david_koski@mac.com at  
>> openSubscriber.com
>> http://www.opensubscriber.com/message/httpcomponents-dev@jakarta.apache.org/7128633.html
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
>> For additional commands, e-mail: dev-help@hc.apache.org
>>
>>
>


Re: Re: async http clients

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Tue, 2008-01-22 at 16:52 -0500, david_koski@mac.com wrote:
> Hi,
> 
> Your suggestion worked well, but I think I ran into a problem with it (using A6, if it matters).  I ended up with a hung IOReactor thread:
> 
> Thread [I/O dispatcher 2] (Suspended)	
> 	KQueueArrayWrapper.register0(int, int, int, int) line: not available [native method]	
> 	KQueueArrayWrapper.setInterest(int, int) line: 99	
> 	KQueueSelectorImpl.putEventOps(SelectionKeyImpl, int) line: 179	
> 	SocketChannelImpl.translateAndSetInterestOps(int, SelectionKeyImpl) line: 733	
> 	SelectionKeyImpl.nioInterestOps(int) line: 87	
> 	SelectionKeyImpl.interestOps(int) line: 65	
> 	IOSessionImpl.clearEvent(int) line: 125	
> 	AsyncHTTPClient$AsyncConnection(DefaultNHttpClientConnection).produceOutput(NHttpClientHandler) line: 183	
> 	AsyncHTTPClient$EventDispatch(DefaultClientIOEventDispatch).outputReady(IOSession) line: 102	
> 	AsyncHTTPClient$EventDispatch.outputReady(IOSession) line: 353	
> 	BaseIOReactor.writable(SelectionKey) line: 109	
> 	BaseIOReactor(AbstractIOReactor).processEvent(SelectionKey) line: 192	
> 	BaseIOReactor(AbstractIOReactor).processEvents(Set) line: 174	
> 	BaseIOReactor(AbstractIOReactor).execute() line: 137	
> 	BaseIOReactor.execute(IOEventDispatch) line: 69	
> 	AbstractMultiworkerIOReactor$Worker.run() line: 281	
> 	Thread.run() line: 613	
> 
> The AsyncHTTPClient class is mine, but it is just very thin wrappers on the default implementations.  Anyway, the thread hangs like this while trying to clear the write interest on the SelectionKey.  I only seem to run into this at high (> 1000 per second) request rates.
> 
> I think this may actually be related to waking up the the IOControl:
> 
>                 conn.requestOutput();
> 
> this ends up here:
> 
> 
>     public void setEvent(int op) {
>         if (this.status == CLOSED) {
>             return;
>         }
>         synchronized (this.key) {
>             int ops = this.key.interestOps();
>             this.key.interestOps(ops | op);
>             this.key.selector().wakeup();
>         }
>     }
> 
> However, several sites suggest that concurrent modification of SelectionKeys is a recipe for disaster:
> 
> http://rox-xmlrpc.sourceforge.net/niotut/index.html
> 
> As a result, if you plan to hang onto your sanity don't modify the selector from any thread other than the selecting thread. This includes modifying the interest ops set for a selection key, registering new channels with the selector, and cancelling existing channels.
> 
> 
> 
> But that is _exactly_ what I am doing here.  The thread that wants the connection is touching the SelectionKey and the IOReactor (I/O dispatcher) thread is also touching it.
> 
> Am I understanding this correctly?
> 

David,

The javadocs of the SelectonKey clearly states the class is threading
safe [1]:

"... Selection keys are safe for use by multiple concurrent threads..."

One certainly should not attempt to access the selector from multiple
threads but it is completely new to me some people think this also
applies to the selection keys. Selection keys would be completely
pointless if they were not threading safe 

Can this be a JRE issue? What is the JRE you are using?

Oleg

[1]
http://java.sun.com/j2se/1.4.2/docs/api/java/nio/channels/SelectionKey.html 


> Thanks,
> David Koski
> 
> 
> -- Oleg Kalnichevski wrote : 
> On Thu, 2007-07-12 at 14:10 -0700, David Koski wrote:
> > Hi,
> > 
> > I have been reading NHttpClient and I think I finally understand how  
> > it all works, but I am a bit stuck with how to use it.  Let's say I  
> > wanted to build something along the lines of a load balancer:  many  
> > incoming connections, many outgoing connections, most are idle or  
> > waiting for a response.
> > 
> > Focusing on the outgoing connections part, I want to have keep-alive  
> > connections to a set of hosts, multiple connections per port.  For  
> > example:
> > 
> > 	LB -> host1:80
> > 	LB -> host1:80
> > 	LB -> host1:80
> > 
> > 	LB -> host2:80
> > 	LB -> host2:80
> > 
> > If I have a queue of operations I want to do, I can see how I might  
> > use a series of ioReactor.connect() calls to create the connections  
> > and have submitRequest() methods in my HttpRequestExecutionHandler  
> > pull them off the queue and service them.
> > 
> > The problem I am having is dealing with the steady state.  I would  
> > like to keep these connections around for a while (and indeed using  
> > the DefaultConnectionReuseStrategy they are kept alive.  However, once  
> > my queue drains and my submitRequest() method returns null, how do I  
> > wake the handlers back up?  I can see any way to get the reactor to  
> > call back into my handler without opening a new connection.
> > 
> > Am I missing something?  Or going about this the wrong way?
> > 
> 
> Hi David
> 
> Just invoke IOControl#requestOutput() (implemented by all NHttp
> connections) and it will cause the I/O reactor to fire up the
> NHttpClientHandler#requestReady() event, which you can use to submit a
> new request on that connection
> 
> Hope this helps
> 
> Oleg
> 
> > Thanks,
> > David Koski
> > 
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jaka...
> > For additional commands, e-mail: httpcomponents-dev-help@jaka...
> > 
> > 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jaka...
> For additional commands, e-mail: httpcomponents-dev-help@jaka...
> 
> 
> --
> This message was sent on behalf of david_koski@mac.com at openSubscriber.com
> http://www.opensubscriber.com/message/httpcomponents-dev@jakarta.apache.org/7128633.html
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
> For additional commands, e-mail: dev-help@hc.apache.org
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Re: Re: async http clients

Posted by da...@mac.com.
Hi,

Your suggestion worked well, but I think I ran into a problem with it (using A6, if it matters).  I ended up with a hung IOReactor thread:

Thread [I/O dispatcher 2] (Suspended)	
	KQueueArrayWrapper.register0(int, int, int, int) line: not available [native method]	
	KQueueArrayWrapper.setInterest(int, int) line: 99	
	KQueueSelectorImpl.putEventOps(SelectionKeyImpl, int) line: 179	
	SocketChannelImpl.translateAndSetInterestOps(int, SelectionKeyImpl) line: 733	
	SelectionKeyImpl.nioInterestOps(int) line: 87	
	SelectionKeyImpl.interestOps(int) line: 65	
	IOSessionImpl.clearEvent(int) line: 125	
	AsyncHTTPClient$AsyncConnection(DefaultNHttpClientConnection).produceOutput(NHttpClientHandler) line: 183	
	AsyncHTTPClient$EventDispatch(DefaultClientIOEventDispatch).outputReady(IOSession) line: 102	
	AsyncHTTPClient$EventDispatch.outputReady(IOSession) line: 353	
	BaseIOReactor.writable(SelectionKey) line: 109	
	BaseIOReactor(AbstractIOReactor).processEvent(SelectionKey) line: 192	
	BaseIOReactor(AbstractIOReactor).processEvents(Set) line: 174	
	BaseIOReactor(AbstractIOReactor).execute() line: 137	
	BaseIOReactor.execute(IOEventDispatch) line: 69	
	AbstractMultiworkerIOReactor$Worker.run() line: 281	
	Thread.run() line: 613	

The AsyncHTTPClient class is mine, but it is just very thin wrappers on the default implementations.  Anyway, the thread hangs like this while trying to clear the write interest on the SelectionKey.  I only seem to run into this at high (> 1000 per second) request rates.

I think this may actually be related to waking up the the IOControl:

                conn.requestOutput();

this ends up here:


    public void setEvent(int op) {
        if (this.status == CLOSED) {
            return;
        }
        synchronized (this.key) {
            int ops = this.key.interestOps();
            this.key.interestOps(ops | op);
            this.key.selector().wakeup();
        }
    }

However, several sites suggest that concurrent modification of SelectionKeys is a recipe for disaster:

http://rox-xmlrpc.sourceforge.net/niotut/index.html

As a result, if you plan to hang onto your sanity don't modify the selector from any thread other than the selecting thread. This includes modifying the interest ops set for a selection key, registering new channels with the selector, and cancelling existing channels.



But that is _exactly_ what I am doing here.  The thread that wants the connection is touching the SelectionKey and the IOReactor (I/O dispatcher) thread is also touching it.

Am I understanding this correctly?

Thanks,
David Koski


-- Oleg Kalnichevski wrote : 
On Thu, 2007-07-12 at 14:10 -0700, David Koski wrote:
> Hi,
> 
> I have been reading NHttpClient and I think I finally understand how  
> it all works, but I am a bit stuck with how to use it.  Let's say I  
> wanted to build something along the lines of a load balancer:  many  
> incoming connections, many outgoing connections, most are idle or  
> waiting for a response.
> 
> Focusing on the outgoing connections part, I want to have keep-alive  
> connections to a set of hosts, multiple connections per port.  For  
> example:
> 
> 	LB -> host1:80
> 	LB -> host1:80
> 	LB -> host1:80
> 
> 	LB -> host2:80
> 	LB -> host2:80
> 
> If I have a queue of operations I want to do, I can see how I might  
> use a series of ioReactor.connect() calls to create the connections  
> and have submitRequest() methods in my HttpRequestExecutionHandler  
> pull them off the queue and service them.
> 
> The problem I am having is dealing with the steady state.  I would  
> like to keep these connections around for a while (and indeed using  
> the DefaultConnectionReuseStrategy they are kept alive.  However, once  
> my queue drains and my submitRequest() method returns null, how do I  
> wake the handlers back up?  I can see any way to get the reactor to  
> call back into my handler without opening a new connection.
> 
> Am I missing something?  Or going about this the wrong way?
> 

Hi David

Just invoke IOControl#requestOutput() (implemented by all NHttp
connections) and it will cause the I/O reactor to fire up the
NHttpClientHandler#requestReady() event, which you can use to submit a
new request on that connection

Hope this helps

Oleg

> Thanks,
> David Koski
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jaka...
> For additional commands, e-mail: httpcomponents-dev-help@jaka...
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jaka...
For additional commands, e-mail: httpcomponents-dev-help@jaka...


--
This message was sent on behalf of david_koski@mac.com at openSubscriber.com
http://www.opensubscriber.com/message/httpcomponents-dev@jakarta.apache.org/7128633.html

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Re: async http clients

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Thu, 2007-07-12 at 14:10 -0700, David Koski wrote:
> Hi,
> 
> I have been reading NHttpClient and I think I finally understand how  
> it all works, but I am a bit stuck with how to use it.  Let's say I  
> wanted to build something along the lines of a load balancer:  many  
> incoming connections, many outgoing connections, most are idle or  
> waiting for a response.
> 
> Focusing on the outgoing connections part, I want to have keep-alive  
> connections to a set of hosts, multiple connections per port.  For  
> example:
> 
> 	LB -> host1:80
> 	LB -> host1:80
> 	LB -> host1:80
> 
> 	LB -> host2:80
> 	LB -> host2:80
> 
> If I have a queue of operations I want to do, I can see how I might  
> use a series of ioReactor.connect() calls to create the connections  
> and have submitRequest() methods in my HttpRequestExecutionHandler  
> pull them off the queue and service them.
> 
> The problem I am having is dealing with the steady state.  I would  
> like to keep these connections around for a while (and indeed using  
> the DefaultConnectionReuseStrategy they are kept alive.  However, once  
> my queue drains and my submitRequest() method returns null, how do I  
> wake the handlers back up?  I can see any way to get the reactor to  
> call back into my handler without opening a new connection.
> 
> Am I missing something?  Or going about this the wrong way?
> 

Hi David

Just invoke IOControl#requestOutput() (implemented by all NHttp
connections) and it will cause the I/O reactor to fire up the
NHttpClientHandler#requestReady() event, which you can use to submit a
new request on that connection

Hope this helps

Oleg

> Thanks,
> David Koski
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: httpcomponents-dev-help@jakarta.apache.org
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: httpcomponents-dev-help@jakarta.apache.org