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 Angel "Java" Lopez @ajlopez On Fri, Feb 14, 2014 at 9:26 PM, Bilal S <bilal.so...@gmail.com> wrote: > Konstantin, > > > > On Fri, Jan 24, 2014 at 2:06 PM, Konstantin Preißer <kpreis...@apache.org > >wrote: > > > Hi all, > > > > for my Java Servlet web applications which run on Tomcat (currently > > 8.0.0-RC 10) on various Windows Server OSes (currently Windows Server > 2012 > > R2), I use the ISAPI Redirector to forward requests from IIS to Tomcat > over > > AJP. I use IIS as primary web server because I also host other websites > > that use different technologies like ASP.Net and PHP (and because IIS > > allows to run web applications as different processes as different user > > accounts, and because I can configure the SSL settings over IIS, and so > on). > > > > The ISAPI Redirector has its job done well in the past and currently I'm > > still using it. Note that I'm only using it to forward requests from a > > single IIS instance to a single Tomcat instance, but not for > load-balancing > > or other features. > > > > > > However, over the time I found some issues which seem to result from the > > changes that Win Server, IIS and other components have experienced over > > time, which I wanted to list here and see how these could be changed. > > > > A possibility that I see is to use an ASP.Net (C#) based redirector > > instead of an ISAPI based redirector as that will have a number of > > advantages - see below. > > > > > > > ==> > 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:: > ====> > > > > 1. > > > > The ISAPI Redirector seems to be quite complicate to configure. You have > > to: > > 1) place the ISAPI redirector DLL in some arbitrary path (the docs > suggest > > to place them in your Tomcat\bin directory) > > > ==> not needed > > > 2) create a virtual directory in your IIS web application which points to > > this path > > > ==> not needed > > > 3) change the handler settings for the virtual directory to allow to > > execute ISAPI dlls > > > ==> not needed > > > 4) add the ISAPI redirector DLL to the list of CGI and ISAPI restrictions > > in IIS > > > ==> not needed > > > 5) add the ISAPI redirector DLL to your web app as ISAPI filter > > > ==> not needed > > > 6) create some registry entries at HKLM\Software\Apache Software > > Foundation\Jakarta Isapi Redirector\1.0 to specify the path of the > virtual > > directory, path to configuration files etc. > > > ==> not needed > > > 7) create configuration files (uriworkersmap.properties, > > worker.properties) and but them in some arbitrary path (the docs suggest > to > > place them in your Tomcat\conf directory) > > > > ==> not needed, configurations are done via the IIS UI and/or an xml > config file > > > > I see a few problems here. > > First, you have to place the ISAPI redirector DLL in some external > > arbitrary path. This can introduce additional maintenance issues as you > > always have to remember this when e.g. moving the server. Because the > docs > > suggest to place them in your Tomcat\bin directory, you might delete that > > file by mistake when you delete your Tomcat installation and create a new > > one. > > The same is true for the config files - if you place them in your Tomcat > > directory, you might delete them when you change your Tomcat config. > > > > Normally, these files do not belong to Tomcat, but to the ISAPI > > redirector, so I would expect to place them somewhere in your IIS web > > application. > > > > E.g, ASP.Net web applications have a "web.config" file in their root > > directory for configuration, and a "bin" directory where .Net assemblies > > can be placed. If you were using an ASP.Net based redirector for example > > (implemented as a managed module), you can place the binary into the > "bin" > > directory of your IIS webapp and configure it by adding it to the > > web.config file. This would also mean that you don't have to create a > > virtual directory any more. > > > > I also got problems with the system-wide registry keys that you need to > > set up for the ISAPI redirector, as they don't allow separate configs for > > different IIS webapps. I once tried to create a > "isapi_redirect.properties" > > with the configuration (instead of using the registry) like it is > described > > on the Tomcat Connectors IIS reference page [1], but I didn't have > success, > > so I reverted back to the registry settings. > > > > Note also that Microsoft has deprecated ISAPI filters and extensions in > > favor of native http modules [2]. > > > > ==> not needed > > > > > > 2. > > > > When using the ISAPI redirector with IIS 7, I got a few problems with > > response buffering - it seemed that IIS buffered the complete response > body > > before starting to send it to the client. However, when I tried this > again > > on IIS 8.5 today, then IIS only buffered a few MB before sending it to > the > > client, so I think this is not a problem any more. > > Note that you can manually specify the amount that IIS should buffer, by > > adding the following in web.config (in <configuration> , > > <system.webServer>): > > > > <handlers> > > <remove name="ISAPI-dll" /> > > <add name="ISAPI-dll" path="*.dll" verb="*" > > modules="IsapiModule" resourceType="File" requireAccess="Execute" > > allowPathInfo="true" responseBufferLimit="1" /> > > </handlers> > > > > ==> flexible buffering works with IIS, default is to mimic ISAPI but byte > and time based buffering / streaming options to client are available. > > > > > 3. > > > > Chunked encoding is disabled by default. > > Personally I think every web server should use chunked encoding if the > > client specifies connection: keep-alive and the content-length is > unknown, > > so that the server doesn't have to close the connection to signal EOF. It > > seems that this is a bit difficult in an ISAPI extension as this feature > > was being considered experimental until a few years ago. > > > > However, for example if you code a managed HTTP module using C#, you can > > just write bytes to the response without having to think about chunked > > encoding, as IIS will do automatically - it is pretty much like writing > to > > the response in a Java Servlet. However I don't know how this would be > done > > in native HTTP modules for IIS. > > > > ==> chunked encoding is default behavior when content size is not known > > > > > > > 4. > > > > By default, IIS applies a limit to POST requests that specify a > > Content-Length and its value exceeds a specific size. This means IIS will > > reject such POST requests before they reach Tomcat (which might allow > such > > a POST request). You can probably change the POST limit in IIS to allow > > bigger request bodys. > > E.g. In a managed module, since .Net 4.5 you can call > > Request.GetBufferlessInputStream(true) [3] to retrieve a bufferless > > InputStream to read the request body, and disable the request length > limit. > > > > ==> might be an interesting consideration. However, bypassing input > limits > may make this less manageable. > > > > > 5. > > > > Sometimes, the ISAPI redirector stops to work - a request times out and > > IIS is not able to shutdown the worker process (w3wp.exe) that uses the > > ISAPI redirector. > > Normally, this does not happen when no configuration is changed on the > > server. > > > > However, in my case, I have multiple IIS web applications that use the > > ISAPI redirector (using the same AppPool), and one web application that > > uses another app pool and uses PHP via FastCGI. > > > > ==> BonCode can have multiple instances even inside the same IIS site, all > hitting different backends. Will not conflict. You can use all IIS > management options. > > > > > Now, everything works. However, if I now open the IIS manager and go to > > the FastCGI settings, then double-click on the php-cgi.exe entry and > > change e.g. the maximum number of instances, then the ISAPI redirector > > suddenly stops working... This means IIS will not answer a request that > > goes to this web application (or even to another app with the same > apppool > > - I haven't tested this). There is no CPU usage. > > Sending a request to a webapp with another apppool (the one with PHP) > > still works. > > > > I have no idea why this happens (and how changing settings for a FastCGI > > application can impact the ISAPI redirector), but the only way to get > > things working again is to kill the w3wp.exe process so that IIS starts a > > new one - then everything will work again. > > > > I think with managed or native IIS modules, such strange issues shouldn't > > happen. ;-) > > > > ==> True > > > > > 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. > > > > > > Now, e.g. .Net 4.5 introduces a new async programming model that allows > > you to write code in blocking/synchronous style, but actually behave as > > async code (using non-blocking I/O if possible). If you use such coding > for > > a managed module to forward requests (and use an async managed module), > > then IIS only needs to take a thread when there's actually code to run > for > > sending additionally data. This means that most of the time the request > > doesn't need a thread, so it should be much more scalable than the > blocking > > model. > > > > I once wrote a SPDY redirector for IIS based on C# (ASP.Net) that > forwards > > request over an SPDY connection, and after switching it to Async I/O, for > > 170 concurrent requests the w3wp.exe only had ~ 35 threads, instead of > ~195 > > threads with blocking I/O [4]. > > > > SPDY allows to multiplex requests on a single TCP connection so this > > combination should allow for a high number of concurrent requests without > > needing a huge number of threads. > > The SPDY redirector already works with Jetty's SPDY/3 implementation, but > > for Tomcat it seems that it does not yet support SPDY/3 (Costin Manolache > > once wrote that he wanted to switch Tomcat's SPDY implementation to > SPDY/3, > > but I didn't see activity in this arey so I don't know what the state of > > SPDY/3 for Tomcat is. > > > > For AJP, however, a TCP connection can only server one request at a time, > > so while an async AJP redirector would not require one thread per > request, > > it still would require one TCP connection per (concurrent) request. > > > > > > 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. > > > > > 8. > > > > In the past there have been reports of problems with the ISAPI redirector > > when using IIS features like "web garden" (when one app pool has multiple > > worker processes) or apppool recycling. I can remember (but I do not have > > references for this atm) that Mladen Turk once said, one should disable > web > > garden (so only 1 process is used per app pool) and disable the apppool > > recycling to avoid problems with the ISAPI redirector. > > I think such problems shouldn't happen when using a managed or native IIS > > module. > > > ==> No issues reported with this scenario. Connector libraries and > configurations can be shared across servers. > > > > > > > > 9. > > > > The 32-bit version of the ISAPI redirector does not work on 64-bit > > versions of Windows. Even when you set the Apppool to allow to execute > > 32-bit applications (this means that the 32-bit version of w3wp.exe will > be > > executed), the 32-bit version of ISAPI redirector does not work. I do not > > know why this is so, but e.g. as .Net is platform-independent, you can > use > > the same assembly (dll) for 32-bit as well as for 64-bit apppools. > > > > ==> Same set of files due to managed code will work for 32/64 bit > > > > > > 10. > > > > Sometimes I see in the Windows event log erros that IIS rejected a > request > > due to bad characters, but the URL that is logged is actually a good one > > (e.g. http://myserver.com/myurl?param=value). If I request this URL, it > > is correctly server, and no new entry is created in the event log. If I > > look in the IIS logs for this URL and the logged time, I only find "200 > OK" > > entries so it seems this URL was correctly served. > > > > My guess is that it was actually a different URL that failed, but the > > ISAPI redirector somehow had overwritten some structure containing the > URL > > so that IIS would log this one instead. However this is only very rarely > so > > I cannot verify what actually happens there. > > > > (Fin) > > > > > > > > Now, I think a future-proof redirector can be one that uses SPDY (or a > > similar protocol) to redirects the requests instead of AJP, because > > 1) it allows multiple concurrent requests per TCP connection, which in > > conjunction with Async I/O should allow for high scalability, and > > 2) it allows to forward WebSocket requests. > > However, there are some issues with SPDY/3 (NPN and header compression) > > that put a few barriers for writing a simple request redirector. > > > > Some time ago, I have written such an SPDY redirector based in C# on a > > managed IIS module [4]. It already works well with Jetty (but Jetty does > > not yet support WebSocket over SPDY/3). However, as Tomcat seems not yet > to > > support SPDY/3, it cannot be used with Tomcat. Another problem is that > > SPDY/3 is still a draft of the SPDY spec which probably change a few > times > > in the future (Google is already working on SPDY/4). For a real usable > SPDY > > redirector, one would probably have to wait until SPDY is final to have a > > common basis for using it with different SPDY servers. > > > > > > Before the SPDY redirector, I also wrote a very simple AJP redirector in > > C# (but still with blocking I/O etc.) for which I only needed ~ 1 day so > it > > should be very easy to write a AJP based replacement for the current > ISAPI > > redirector. > > > > Personally, I would like to get rid of the ISAPI based redirector for > > Tomcat in the near future due to the above mentioned issues. My > preference > > would be to continue implementing the C#-based AJP redirector (but it > will > > probably need a rewrite), or if Tomcat already supports SPDY/3 in that > > time, use the SPDY redirector. > > > > However, I'm wondering about the ISAPI redirector which is available at > > the Tomcat website. From the docs one can see that the ISAPI redirector > is > > already a bit old as they still talk about Windows NT 4.0 and Windows 98 > > (and PWS). What do you think about this? Should the ISAPI redirector > still > > stay? Is SPDY the right way for forwarding requests to Tomcat in the > future? > > > > Thanks! > > > > > > Regards, > > Konstantin Preißer > > > > ==> There is much to be gained by a fresh look at IIS and Tomcat > interoperability and adjust it for todays problem set. > > -Bilal >