You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@hc.apache.org by Sam Berlin <sb...@limepeer.com> on 2005/06/06 02:13:36 UTC

Blocking & Non-Blocking I/O

Hi Folks,

I recall earlier posts mentioning that HttpClient 4.0 was going to offer
blocking & non-blocking variations, so that multiple requests (or responses,
in the case of the server side) could use a single thread.  Since I did
offer LimeWire's support with some of HttpClient 4.0's development, I figure
I should follow up on that. :)

We've recently completed converting LimeWire's messaging code to be
non-blocking while still allowing blocking use.  The package has two
external depencies (used in a single file, for easier error reporting) which
can easily be removed (other than that, it uses commons logging & java.net,
java.util, java.io, and java.nio classes).

The architecture may work well for HttpClient.  The basic concept is that
reading & writing use the decorator pattern.  So, for instance, you could
have a HttpHeaderWriter, HttpBodyWriter, and a DeflaterWriter.  When writing
headers, you would set the 'writer' to be an HttpHeaderWriter.  When writing
the body, you would set the writer to be the HttpBodyWriter, potentially
settings its writer to be the DeflaterWriter.  With reading, it'd be very
similar, an HttpHeaderReader, HttpBodyReader, and InflaterReader.  There's
also the equivilent of BufferedOutputStream, a DelayedBufferWriter, which
one-ups BufferedOutputStream in the sense that it will try to buffer all
output (writing only when the buffer is full, to reduce the nmber TCP
packets sent), but if the buffer hasn't filled in X milliseconds, it will
force the data to be written.  It's also possible to add a ThrottleWriter
(and share a Throttle among multiple ThrottleWriters) which will limit the
outgoing throughput (allowing a fair share for each ThrottleWriter).

It is possible to use blocking i/o for a portion of the transfer, and then
convert it to non-blocking, although I'm not sure how useful it is for
HttpClient.  Internally, the transfer is actually non-blocking, but it
emulates the blocking portion (somewhat better than Sun's blocking emulation
with configureBlocking(true)).  To use it, all you have to do is change new
Socket(...) to new NIOSocket(...), and new ServerSocket(...) to new
NIOServerSocket(...).  I do not know how convenient this is with the
SocketFactories that HttpClient has.  I imagine there could be new
NIOFactories which would subclass the existing ones.

Non-blocking connecting currently isn't supported (neither is non-blocking
accepting), but they're trivial to add and we're likely going to add support
soon.

As an example DeflaterWriter & InflaterReader, see
http://limewire.org/fisheye/viewrep/limecvs/core/com/limegroup/gnutella/conn
ection/DeflaterWriter.java?r=1.2 (Deflater) and
http://limewire.org/fisheye/viewrep/limecvs/core/com/limegroup/gnutella/conn
ection/InflaterReader.java?r=1.2 (Inflater).  Right now they're in a
separate package, but they'd fit really well in the io package.

As an example 'top level writer/reader', see our MessageReader &
MessageWriter:
http://limewire.org/fisheye/viewrep/limecvs/core/com/limegroup/gnutella/conn
ection/MessageReader.java?r=1.4 and
http://limewire.org/fisheye/viewrep/limecvs/core/com/limegroup/gnutella/conn
ection/MessageWriter.java?r=1.2 .

Thanks,
 Sam


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


Re: Blocking & Non-Blocking I/O

Posted by Sam Berlin <sb...@gmail.com>.
Thanks for the vote of confidence, Ortwin.  It'll be good to work on
HttpClient, given that I do end up with some spare time.  (Or, if
there's any companies out there that would like to sponsor some work.
:) )

Thanks,
 Sam

On 7/21/05, Ortwin Glück <od...@odi.ch> wrote:
> Sam Berlin wrote:
> > I'm in the process of finishing up my day job, and then am doing a bit
> > of traveling (if any of you folks will be at Burning Man, I'll be at
> > the 'Elation Station' camp), and will find myself with more time come
> > October.  Since I'm already pretty familiar with HttpClient, I suppose
> > it'd make sense to try and get some work done on it.  We'll see how
> > things go.
> 
> Sam, it would be terrific to have you on board!
> 
> Ortwin Glück
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org
> 
>

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


Re: Blocking & Non-Blocking I/O

Posted by Ortwin Glück <od...@odi.ch>.
Sam Berlin wrote:
> I'm in the process of finishing up my day job, and then am doing a bit  
> of traveling (if any of you folks will be at Burning Man, I'll be at  
> the 'Elation Station' camp), and will find myself with more time come  
> October.  Since I'm already pretty familiar with HttpClient, I suppose  
> it'd make sense to try and get some work done on it.  We'll see how  
> things go.

Sam, it would be terrific to have you on board!

Ortwin Glück

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


Re: Blocking & Non-Blocking I/O

Posted by Sam Berlin <sb...@limepeer.com>.
Hi Oleg & folks,

Thanks for your detailed response, and my apologies for taking so long  
to respond to them.  I suppose when I read that HttpClient was going to  
make use of NIO, I assumed it was going to be using a single-threaded  
design & non-blocking components (which, by their very nature, are more  
complex than blocking designs).  For the client side, using NIO makes  
sense a couple of scenarios.  These range from swarmed downloading, to  
many concurrent downloads, to crawlers.  On a server, a client-side use  
of HttpClient can justify creating up to 500 threads, but it's never  
justifiable on a consumer's computer -- programs must play nicely with  
others, and that means keeping resources (and threads) down.

You're 100% correct about the servlet 2.x API, though.  It's a big  
problem.  From what little I've read about the matter, the author(s) of  
Jetty decided to write their own version of the API in an event-based  
manner, so it could work with non-blocking & blocking frameworks.

I'm in the process of finishing up my day job, and then am doing a bit  
of traveling (if any of you folks will be at Burning Man, I'll be at  
the 'Elation Station' camp), and will find myself with more time come  
October.  Since I'm already pretty familiar with HttpClient, I suppose  
it'd make sense to try and get some work done on it.  We'll see how  
things go.

Thanks,
  Sam

On Jun 13, 2005, at 4:57 PM, Oleg Kalnichevski wrote:

> Hi Sam and all
>
> I finally had time to take a closer look at this code and I think this
> is certainly something you want to draw upon in the future when
> developing http-asynch. However, exactly when this is going to happen  
> is
> a matter how we set priorities.
>
> This is how I see things in a sort of semi-random rambling, so take it
> for what it is worth.
>
> (1) HttpCommon already makes use of NIO, albeit in the blocking mode.
> So, it should already benefit from performance improvements offered by
> new *Buffer and CharsetEncoder/CharsetDecoder classes
>
> (2) A significantly more complex non-blocking I/O hardly makes a lot of
> sense on the client side, where the number of concurrent connections
> should never exceed a few dozens at max. The extra complexity of non-
> blocking I/O is justified only when the number of concurrent  
> connections
> gets over 500.
>
> (3) The servlet 2.x API is still based on the blocking InputStream /
> OutputStream paradigm. Currently Servlet 2.x API is de-facto standard
> server-side HTTP framework, which limits the pool of potential users  
> for
> non-blocking HTTP.
>
> (4) Embedded HTTP servers may never be required to deal with hundreds  
> of
> concurrent connections, which again makes non-blocking I/O more of a
> burden than any real benefit.
>
> (5) At the same an NIO based, scalable server-side HTTP framework is
> probably the only way we can attract any interest beyond our existent
> user base.
>
> So, the real question is how we set our priorities and allocate our
> rather limited resources and what should happen first: promotion to
> Jakarta level, HttpClient 4.0 (and therefore http-cookie, http-auth,
> and other dependencies), a lightweight server based on a subset of
> servlet API, Tomcat Connector based on HttpCommon, something else? In
> which sequence?
>
> What do you think?
>
> Oleg
>
>
> On Sun, 2005-06-05 at 20:13 -0400, Sam Berlin wrote:
>> Hi Folks,
>>
>> I recall earlier posts mentioning that HttpClient 4.0 was going to  
>> offer
>> blocking & non-blocking variations, so that multiple requests (or  
>> responses,
>> in the case of the server side) could use a single thread.  Since I  
>> did
>> offer LimeWire's support with some of HttpClient 4.0's development, I  
>> figure
>> I should follow up on that. :)
>>
>> We've recently completed converting LimeWire's messaging code to be
>> non-blocking while still allowing blocking use.  The package has two
>> external depencies (used in a single file, for easier error  
>> reporting) which
>> can easily be removed (other than that, it uses commons logging &  
>> java.net,
>> java.util, java.io, and java.nio classes).
>>
>> The architecture may work well for HttpClient.  The basic concept is  
>> that
>> reading & writing use the decorator pattern.  So, for instance, you  
>> could
>> have a HttpHeaderWriter, HttpBodyWriter, and a DeflaterWriter.  When  
>> writing
>> headers, you would set the 'writer' to be an HttpHeaderWriter.  When  
>> writing
>> the body, you would set the writer to be the HttpBodyWriter,  
>> potentially
>> settings its writer to be the DeflaterWriter.  With reading, it'd be  
>> very
>> similar, an HttpHeaderReader, HttpBodyReader, and InflaterReader.   
>> There's
>> also the equivilent of BufferedOutputStream, a DelayedBufferWriter,  
>> which
>> one-ups BufferedOutputStream in the sense that it will try to buffer  
>> all
>> output (writing only when the buffer is full, to reduce the nmber TCP
>> packets sent), but if the buffer hasn't filled in X milliseconds, it  
>> will
>> force the data to be written.  It's also possible to add a  
>> ThrottleWriter
>> (and share a Throttle among multiple ThrottleWriters) which will  
>> limit the
>> outgoing throughput (allowing a fair share for each ThrottleWriter).
>>
>> It is possible to use blocking i/o for a portion of the transfer, and  
>> then
>> convert it to non-blocking, although I'm not sure how useful it is for
>> HttpClient.  Internally, the transfer is actually non-blocking, but it
>> emulates the blocking portion (somewhat better than Sun's blocking  
>> emulation
>> with configureBlocking(true)).  To use it, all you have to do is  
>> change new
>> Socket(...) to new NIOSocket(...), and new ServerSocket(...) to new
>> NIOServerSocket(...).  I do not know how convenient this is with the
>> SocketFactories that HttpClient has.  I imagine there could be new
>> NIOFactories which would subclass the existing ones.
>>
>> Non-blocking connecting currently isn't supported (neither is  
>> non-blocking
>> accepting), but they're trivial to add and we're likely going to add  
>> support
>> soon.
>>
>> As an example DeflaterWriter & InflaterReader, see
>> http://limewire.org/fisheye/viewrep/limecvs/core/com/limegroup/ 
>> gnutella/conn
>> ection/DeflaterWriter.java?r=1.2 (Deflater) and
>> http://limewire.org/fisheye/viewrep/limecvs/core/com/limegroup/ 
>> gnutella/conn
>> ection/InflaterReader.java?r=1.2 (Inflater).  Right now they're in a
>> separate package, but they'd fit really well in the io package.
>>
>> As an example 'top level writer/reader', see our MessageReader &
>> MessageWriter:
>> http://limewire.org/fisheye/viewrep/limecvs/core/com/limegroup/ 
>> gnutella/conn
>> ection/MessageReader.java?r=1.4 and
>> http://limewire.org/fisheye/viewrep/limecvs/core/com/limegroup/ 
>> gnutella/conn
>> ection/MessageWriter.java?r=1.2 .
>>
>> Thanks,
>>  Sam
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
>> For additional commands, e-mail:  
>> httpclient-dev-help@jakarta.apache.org
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org
>


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


Re: Blocking & Non-Blocking I/O

Posted by Oleg Kalnichevski <ol...@apache.org>.
Hi Sam and all

I finally had time to take a closer look at this code and I think this
is certainly something you want to draw upon in the future when
developing http-asynch. However, exactly when this is going to happen is
a matter how we set priorities.

This is how I see things in a sort of semi-random rambling, so take it
for what it is worth.

(1) HttpCommon already makes use of NIO, albeit in the blocking mode.
So, it should already benefit from performance improvements offered by
new *Buffer and CharsetEncoder/CharsetDecoder classes

(2) A significantly more complex non-blocking I/O hardly makes a lot of
sense on the client side, where the number of concurrent connections
should never exceed a few dozens at max. The extra complexity of non-
blocking I/O is justified only when the number of concurrent connections
gets over 500. 

(3) The servlet 2.x API is still based on the blocking InputStream /
OutputStream paradigm. Currently Servlet 2.x API is de-facto standard
server-side HTTP framework, which limits the pool of potential users for
non-blocking HTTP.

(4) Embedded HTTP servers may never be required to deal with hundreds of
concurrent connections, which again makes non-blocking I/O more of a
burden than any real benefit.

(5) At the same an NIO based, scalable server-side HTTP framework is
probably the only way we can attract any interest beyond our existent
user base. 

So, the real question is how we set our priorities and allocate our
rather limited resources and what should happen first: promotion to
Jakarta level, HttpClient 4.0 (and therefore http-cookie, http-auth,
and other dependencies), a lightweight server based on a subset of
servlet API, Tomcat Connector based on HttpCommon, something else? In
which sequence?

What do you think?

Oleg


On Sun, 2005-06-05 at 20:13 -0400, Sam Berlin wrote:
> Hi Folks,
> 
> I recall earlier posts mentioning that HttpClient 4.0 was going to offer
> blocking & non-blocking variations, so that multiple requests (or responses,
> in the case of the server side) could use a single thread.  Since I did
> offer LimeWire's support with some of HttpClient 4.0's development, I figure
> I should follow up on that. :)
> 
> We've recently completed converting LimeWire's messaging code to be
> non-blocking while still allowing blocking use.  The package has two
> external depencies (used in a single file, for easier error reporting) which
> can easily be removed (other than that, it uses commons logging & java.net,
> java.util, java.io, and java.nio classes).
> 
> The architecture may work well for HttpClient.  The basic concept is that
> reading & writing use the decorator pattern.  So, for instance, you could
> have a HttpHeaderWriter, HttpBodyWriter, and a DeflaterWriter.  When writing
> headers, you would set the 'writer' to be an HttpHeaderWriter.  When writing
> the body, you would set the writer to be the HttpBodyWriter, potentially
> settings its writer to be the DeflaterWriter.  With reading, it'd be very
> similar, an HttpHeaderReader, HttpBodyReader, and InflaterReader.  There's
> also the equivilent of BufferedOutputStream, a DelayedBufferWriter, which
> one-ups BufferedOutputStream in the sense that it will try to buffer all
> output (writing only when the buffer is full, to reduce the nmber TCP
> packets sent), but if the buffer hasn't filled in X milliseconds, it will
> force the data to be written.  It's also possible to add a ThrottleWriter
> (and share a Throttle among multiple ThrottleWriters) which will limit the
> outgoing throughput (allowing a fair share for each ThrottleWriter).
> 
> It is possible to use blocking i/o for a portion of the transfer, and then
> convert it to non-blocking, although I'm not sure how useful it is for
> HttpClient.  Internally, the transfer is actually non-blocking, but it
> emulates the blocking portion (somewhat better than Sun's blocking emulation
> with configureBlocking(true)).  To use it, all you have to do is change new
> Socket(...) to new NIOSocket(...), and new ServerSocket(...) to new
> NIOServerSocket(...).  I do not know how convenient this is with the
> SocketFactories that HttpClient has.  I imagine there could be new
> NIOFactories which would subclass the existing ones.
> 
> Non-blocking connecting currently isn't supported (neither is non-blocking
> accepting), but they're trivial to add and we're likely going to add support
> soon.
> 
> As an example DeflaterWriter & InflaterReader, see
> http://limewire.org/fisheye/viewrep/limecvs/core/com/limegroup/gnutella/conn
> ection/DeflaterWriter.java?r=1.2 (Deflater) and
> http://limewire.org/fisheye/viewrep/limecvs/core/com/limegroup/gnutella/conn
> ection/InflaterReader.java?r=1.2 (Inflater).  Right now they're in a
> separate package, but they'd fit really well in the io package.
> 
> As an example 'top level writer/reader', see our MessageReader &
> MessageWriter:
> http://limewire.org/fisheye/viewrep/limecvs/core/com/limegroup/gnutella/conn
> ection/MessageReader.java?r=1.4 and
> http://limewire.org/fisheye/viewrep/limecvs/core/com/limegroup/gnutella/conn
> ection/MessageWriter.java?r=1.2 .
> 
> Thanks,
>  Sam
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org
> 


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