tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Konstantin Preißer <kpreis...@apache.org>
Subject RE: Status of the current IIS ISAPI Redirector for Tomcat
Date Sat, 15 Feb 2014 14:00:44 GMT
Hi Angel and Bilal,

thank you for your replies.


> -----Original Message-----
> From: Angel Java Lopez [mailto:ajlopez2000@gmail.com]
> Sent: Saturday, February 15, 2014 11:59 AM
> To: Tomcat Users List
> Subject: Re: Status of the current IIS ISAPI Redirector for Tomcat
> 
> Very interesting!
> 
> Yes, managed code is the path to follow.
> 
> First idea non-blocking IO (from C# client side): use the new async/await
> for the communication. But force to use the new .NET framework and Visual
> Studio. And await is a wait on the current threads:
> 
> http://msdn.microsoft.com/en-us/library/hh750082.aspx
> 
> Maybe, a "node.js" approach, with a callback:
> 
> http://stackoverflow.com/questions/16894907/creating-asynchronous-
> methods-with-task-factory-and-callback
> and only .NET 4.0:
> http://msdn.microsoft.com/en-us/library/dd537612(v=vs.100).aspx
> 
> I don't still see the value of await: it blocked the current thread. I
> guess it is better to use a callback

A "await" on a Task in C# should internally return the current thread back to a threadpool,
and use a callback on another thread to continue execution of the method when the Task is
finished, so that threads are not blocked when waiting e.g. for an I/O operation to complete.
For a full utilization of asynchronous I/O, one would not only have to use async read/write
operations when forwarding the request to Tomcat, but also async flush the response body at
IIS to the client (and async read the request body). Although the .Net HttpResponse also seem
to have BeginFlush() and EndFlush() methods that apply the old-style async programming pattern,
in the SPDY Redirector (see below) I'm using Task.Factory.FromAsync(...) to convert these
Begin/End-Methods into one that returns a Task, so that it can be integrated into the existing
Task-based async code.

For async flush and read operations at IIS to work, one will need to create an async module
(IHttpModule, but use context.AddOnBeginRequestAsync() methods to add event handlers) or an
async handler (derived from HttpTaskAsyncHandler).

This is the approach that I use on a draft of an SPDY redirector that can already be tested
with Jetty (but not yet with Tomcat), see [1]. After switching from blocking I/O to async
methods, the number of threads of the IIS apppool (w3wp.exe) was greatly reduced when having
a slow output producer (servlet) on the Jetty side, and a fast client connecting to IIS (but
should also work for the more likely scenario: A fast output producer (Jetty) and a slow client);
as with blocking I/O, the IIS threads would spend most of their time with doing nothing, whereas
with the async approach, they can do other things meanwhile.

This approach suits the idea of a multiplexing SPDY as you can send multiple requests on a
single SPDY connection, so it doesn't block resources like sockets or threads for the duration
of an request. With SPDY, it should also be possible to forward Websocket connections which
is AFAIK not possible with AJP.


> 
> Angel "Java" Lopez
> @ajlopez
> 
> 
> On Fri, Feb 14, 2014 at 9:26 PM, Bilal S <bilal.soylu@gmail.com> wrote:
> 
> > Konstantin,

<snip>

> > ==>
> > You raise good points. I have run into similar issues and thus created  my
> > own project outside the Apache foundation three years ago (BonCode). It
> is
> > a C# based AJP connector. It can currently be used with Tomcat, JBOSS,
> > Jetty. From support requests I am surmising that is currently bundled with
> > software from a few manufacturers including: EMC, CSC, Siemens and
> others
> > instead of ISAPI redirector.
> >
> > Thus, I do encourage the update of the current IIS connection mechanism
> to
> > a more up-to-date method. Using a managed code mechanism is the way
> to go
> > in my opinion.
> > In the long run SPDY may also be of interest for the same purpose. The
> more
> > choices the better.
> >
> > The following are differences already in existence with BonCode and in
> > response to your extensive writing, only read on if you are curious::
> > ====>

Thank you for you detailed response, this is very helpful.

<snip>

> > > 6.
> > >
> > > As far as I can see, the ISAPI redirector uses blocking I/O when
> > > forwarding requests to Tomcat.
> > >
> > > This means when a slow client sends a request to IIS which gets
> forwarded
> > > to Tomcat, and Tomcat starts to send the response, in the IIS worker
> > > process at least 1 Thread will be dedicated to this request as long as it
> > > is not finished. This means if 500 slow clients concurrently send
> > requests
> > > to IIS (which get forwarded), IIS has to create 500 threads in the
> > > w3wp.exe. This can be a problem in terms of scalability, if lots of
> > clients
> > > send concurrent requests to your server.
> > >
> > > ==> Not most elegant but BonCode will time out the connection based on
> > IIS
> > AppPool setting and reuse. You can also do a similar thing on the Tomcat
> > side. The nature of AJP does not allow multiplexing a connection, so it
> > needs to be dedicated to a client.
> >
> >
> > > The recently released Servlet 3.1 spec allows to use non-blocking I/O
> > when
> > > reading the request body or writing the response body, so that Tomcat
> > > doesn't have to dedicate a thread for the lifetime of the request, but
> > only
> > > take one from a Therad pool when further data can be sent to (or read
> > from)
> > > the client. IIS however would still need to dedicate a thread for the
> > > request. Another problem is that at least IIS 8 only seems to create
> > > additional threads very slowly (1 Thread per second) when its thread pool
> > > is exhausted, which can happen if a few slow clients concurrently send
> > > requests handled by the ISAPI redirector. So some of the clients would
> > have
> > > to wait very long until a thread is created which can handle their
> > request.
> > >
> >
> > ==> Interesting idea, would need to understand better how this applies to
> > the connector and communication via AJP. Currently BonCode creates and
> > maintains a larger base thread-pool, and times them out slowly so the
> under
> > load behavior is more graceful with less create/destroy overhead.
> >

AFAIK, the behavior of IIS to create additional threads (when the others are blocked) very
slowly also happens with managed code like an IHttpHandler, but only when the handler flushes
the output or if output buffering is disabled (response.OutputBuffer = false). Otherwise,
if IIS is able to buffer the whole content to be sent to the client and the handler method
returns without doing a flush operation, IIS will be able to asynchronously send the buffered
content to the client.

However, this was based on some observasions; I have not examined in detail how IIS handles
the output buffer and/or creating additional threads.

The reason for flushing in my case (SPDY redirector) / disable output buffering for the ISAPI
redirector was, that otherwise IIS might try to buffer the whole response - e.g. if the client
requests a 1 GB file, IIS would try to buffer 1 GB before sending it to the client. However,
on another try, I found that IIS flushed after each buffering some MBs of the response, but
I think this then happens synchronously on the Stream.Write() methods, so it would also block
the threads, whereas flushing asynchronously should not block it.

 <snip>

> > > 7.
> > >
> > > The ISAPI redirector handles requests to directories like WEB-INF by
> > > itself (rejecting it with 404, or just disconnecting the client).
> > However,
> > > if it is just forwarding requests, then my point of view would be that it
> > > should not reject requests by itself, but instead let this do Tomcat (or
> > > whatever AJP server is behind), because Tomcat needs to also do this if
> > you
> > > directly connect to it over HTTP.
> > > I can see a reason for rejecting requests to WEB-INF at IIS level if IIS
> > > it is configured to serve static resources directly, and only forward
> > > requests to Tomcat. However, personally I never to this due to the
> > security
> > > implications, and the performance benefit for IIS serving static
> > resources
> > > directly instead of letting Tomcat serve them was rather not noticeable
> > for
> > > me.
> > >
> > > ==> Wouldn't this present an easy exploit path especially if IIS and
> > Tomcat use the same physical path and handlers are misconfigured, e.g.
> when
> > using servlets. I do think the WEB-INF blocking is the safer option.

Yes, if IIS is configured to serve resources from the same physical path as Tomcat then a
redirector should block such access. In my case, on the websites that use the ISAPI redirector,
I redirect every request to Tomcat (and IIS uses a different physical path than Tomcat).

> > >
> >
> > ==> There is much to be gained by a fresh look at IIS and Tomcat
> > interoperability and adjust it for todays problem set.
> >
> > -Bilal


Thanks!

Regards,
Konstantin Preißer


[1] http://markmail.org/message/ojknieujkcchxqla


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Mime
View raw message