tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Attila Szegedi" <>
Subject Re: nbio connector
Date Tue, 08 Jan 2002 16:13:27 GMT

----- Original Message ----- 
From: "Remy Maucherat" <>
To: "Tomcat Developers List" <>
Sent: 2002. január 8. 16:35
Subject: Re: nbio connector

> > My primary goal for bringing the code in the public is that I want
> > to build a HTTP/1.1 connector for Tomcat 4.0 based on it
> I don't think you can have a nbio connector with a compliant servlet
> container, because the J2EE spec mandates at the moment: 1 thread <-> 1
> request.

I don't think I conflict with this requirement. In fact, to execute a servlet's service()
method still requires a separate thread. In my design, the connector first reads the request
line and the headers in a non-blocking fashion, naturally multiplexing up to 63 requests on
a single thread. I have a working HTTP processing state machine for that. (You simply HAVE
to write state machines in nb world, since you can't encapsulate the algorithm in a single-thread
linear flow of methods because of multiplexing). Then it buffers the whole request body using
multiplexed non-blocking code. This buffering is done using a special non-blocking pipe (more
on this below). After that, it constructs the request and response objects, and fires off
container.invoke(req, resp) on a separate thread. The response object also has a non-blocking
pipe that to the servlet masquerades as a ServletOutputStream.
All this is done with the goal of completely avoiding any thread running container.invoke(req,
resp) to EVER block on a socket read or write.

A special non-blocking pipe is more-or-less an ordinary pipe: one input stream and one output
stream, however it does not have a fixed-size buffer (because that would block when the buffer
gets full), instead it manages a growing list of buffers and can hold any size of buffered
bytes. It's used both for buffering request body, and for buffering the response. The response
pipe is written to by the servlet and read from by the non-blocking code that transfers its
data to the socket channel; so in the response phase the pipe buffers that part of the output
that the servlet has already generated, but that still couldn't get pushed through the network
interface. Thus, it eliminates I/O block in response.getOutputStream().write(...) calls. As
an additional memory optimization, it starts buffering in memory, but if the buffered content
gets large it switches to buffering in a memory-mapped file (also new in JDK 1.4).

> That requirements makes nbio much less interesting over the current since
> you would need a big thread pool.

With my design, you still need one thread/request but only for the time required to process
container.invoke() (that is, while the filters and servlets run). Since the design also eliminates
I/O blocking in those threads, they can complete as quickly as their code otherwise allows,
so the overall requirement for threads is substantially lower than in a blocking implementation.

> > , and could
> > use a helping hand here and there. In fact, I already have much of
> > the code for building the HttpServletRequest object, but to keep
> > it really elegant I'll need some help from the Tomcat community.
> > Most notably, much of the code duplications could go away if Catalina
> > code in  org.apache.catalina.connectors.http was more reusable
> > (some classes are package-private and some public classes take
> > package-private classes in a constructor argument etc.).
> > I'll return to these issues on this list after I've properly set
> > up the project on SourceForge.
> Don't use that code, as it is not very efficient / memory intensive, etc.
> Something more useful would be to write a nbio selector for the HTTP/1.1
> connector I'm writing in j-t-c.
> For the connector, nbio is the last optimization which should be done. There
> are much bigger hotspots than the time spent in in the connector
> which ships with 4.0.x ;-)
> Also, why not contributing the thing to the core project (if it manages to
> get around the problem mentioned above, of course), instead of developing it
> separately ?

There are several reasons:

1. It needs JDK 1.4 to compile, and I believe Tomcat should not rely on the not-yet-final
1.4 JDK.
I know, this can be dealt with using conditional compilation in the build.xml file, as it
does now with optional components.
2. My framework as it stands now is a generic framework for implementing arbitrary TCP/IP
services in a non-blocking fashion. Having a Tomcat connector built upon it is only one possible
application. SMTP, FTP, etc. servers can also be written upon this framework.
3. It would be tedious for me to send in CVS patches over long run. While I have no problem
with this approach in general (I have already contributed to both Velocity and Ant by sending
patches to committers), on SourceForge I have my own CVS I can commit to right now, and I
need this level of control. I don't doubt, that the community would grant me committer status
on Tomcat over time if I contribute regularly, however I plan to work intensively on this
code and I fear the inability to have a CVS to which I can commit to right from the start
would somewhat bog me down.

If the Tomcat HTTP connector comes to life as part of the nbserver project and works fine,
I'll have no objections to migrating it into Tomcat source tree. In fact, since I'm publishing
the code under Apache-style license, I *CAN NOT* have any objections if it ever gets transferred
into Tomcat source tree - either with or without my assistance. :-)


> Remy

View raw message