I had a look at the balancer, and it appears to work using redirects, i.e. throwing an HTTP 302 and making each JVM appear as a different URL. I can't do this since I want consistency of externally visible URLs.

The clustering stuff in TC5 is aimed at session persistence and failover, and that is solving a somewhat different problem - we actively don't want persistent sessions, as the cost of them outweighs the marginal value - a typical JVM will stay up for weeks, and you can gracefully shut it down without cutting anyone off at the knees.

The URL rewriting certainly works, but there is the issue of the session cookies which Catalina produces using the internal path, which become non-useful - I guess suppressing them is a 2-3 line patch which isn't too awful.

The other idea one of our developers had here was to customise the "invoker".

Cheers
Dave

Shapira, Yoav wrote:

Hi,
The options for URL rewriting in tomcat get discussed frequently on this
list.  Feel free to search the list archives for complete discussions.
Users usually go the Filter route, which is illustrated by the Balancer
webapp that ships with tomcat 5.  That webapps is not coincidentally
similar to what you calla Dispatcher webapp below.

The fake request URI solution is ugly, but sometimes ugly approaches are
the only feasible thing.

Tomcat now has built-in clustering,
http://jakarta.apache.org/tomcat/tomcat-5.0-doc/cluster-howto.html.  An
alternative approach written before the current tomcat clustering code
was available is illustrated at
http://jakarta.apache.org/tomcat/tomcat-5.0-doc/cluster-howto.html.

Yoav Shapira
Millennium Research Informatics




-----Original Message-----
From: David Crooke [mailto:[EMAIL PROTECTED]
Sent: Tuesday, May 25, 2004 2:13 PM
To: 'Tomcat Users List'
Subject: Tomcat alternatives to replace JServ zone URL abstraction


Hi all

Please bear with me as this is a little complex / indirect - I'll
explain below why the JServ URL -> zone name abstraction is useful, and
then present a couple of workarounds I've thought of for trying to
implement the equivalent capability on top of Tomcat. I'd appreciate a
critique of these ideas from experienced Tomcat users.

We still run JServ - it's simple, but it's very solid and it works very
well. However, it's end of lifed, and while we've only patched it once*
since, I'm also contemplating what it would take to move our main
application server farm to Tomcat, which would get us out of that
business and open up other upgrade paths.

A feature of JServ which we use, and which Tomcat does not appear to
have an equivalent to, is the ability for the Apache layer to map URLs
to JServ zones (c.f. Tomcat webapps), and thus put a layer of
abstraction between the URL and the servlet which gets invoked, which


is


under Apache's control. As far as I can tell, in Tomcat if the URL
passed to Tomcat is "/foo" then the webapp name must be "/foo"

We exploit this to make our upgrade process seamless to clients and
eliminate the need for downtime. The setup is like this:

  * We have about 250 customer sites running a shared Apache
    configuration, and several pools of JServ appservers behind them.
  * Each JServ JVM has the same config with multiple zones; each zone
    contains a different releases of our software.
  * Each client's site has an Apache NameVirtualHost and is mapped to
    a zone, and thus a particular version of our software:

       ApJServMount /site balanace://appservers-grp1/v1

  * Application "Foo" is invoked with a URL of the form
    http://www.customer.com/site/Foo

When we ship an upgrade, we install the new software in a new zone by
cycling the JVM's in and out of service, with no service disruption.
Then, to switch a client over to a new version of the software, we just
change the apache config, as below, and do "apachectl graceful".

ApJServMount /site balanace://appservers-grp1/v2

The URL for the application does not change, and the new version is
picked up.

The beauty of this abstraction is it allows us to upgrade individual
sites independently of each other, and more importantly, independently
of the resource allocation of sites to pools of JVMs, e.g.

<VirtualHost>
   NameVirtualHost www.site1.com
   ApJServMount /site balance://appservers-grp1/v1
</VirtualHost>
<VirtualHost>
   NameVirtualHost www.site2.com
   ApJServMount /site balance://appservers-grp1/v2
</VirtualHost>

*Possible Solutions*

Here are some ideas I've thought of, I'd be interested in a critique.
Bear in mind the essential objective to keep the external URLs


identical.


0. Use separate Tomcat JVMs for different software versions; each has
one webapp called "/site"

This would work cleanly, but has two major drawbacks: (i) it requires
additional resources (at minimum, RAM to support a pool of JVMs), and
(ii) assuming that you're controlling extra resources needed by using
n+1 groups of JVMs and migrating a group at a time, it constrains the
freedom of what sites get migrated when and forces it to be correlated
with, since the first group of migrated sites end up in the first pool
of new JVMs, etc.

For these reasons, this solution isn't really adequate.


1. Map URLs in the Apache layer using mod_rewrite, and abstract HttpServletRequest.getRequestURI() in the application

This seems to be the most promising and least invasive, and I've
prototyped it and it works. Fortunately, all of our servlets are


derived
from a common parent class in which we create our own "wrapper" for the


HttpServletRequest/Response object, let's call it HomeGrownRequest,
which gets passed in API calls etc.

So, in Apache we would do this:

RewriteEngine On
RewriteRule ^/site/(.*)$ /v1/$1 [PT]
JkMount /v1/* appservers-grp1

In Tomcat, we'd create one webapp for each product version. Tomcat will
see the request URL as /v1/Foo and will invoke the "v1" webapp (product
version).

In our own Java code, instead of calling
HttpServletRequest.getRequestURI() we call
HomeGrownRequest.getRealRequestURI() which is implemented like this:

public String getRealRequestURI() {
  String foo = my_http_servlet_request.getRequestURI();
  return "/site" + foo.substring(foo.indexOf("/",2));
}

The other issue with this would be pushing the appropriate cookies -


our


session handling already pushes its own cookies on top of JServ's ones
so not a big deal.


2. Do the mapping in Tomcat, using servlet context request forwarding, and create a "dispatcher" webapp

As per option 1, each product version is installed in a different
webapp. Control of the mapping of sites to product versions moves to


the


appserver layer, and additional webapp called "site" is created which
picks up this information and redispatches the request within Tomcat
using RequestDispatcher.forward(). The Apache side is fixed and looks
like this:

JkMount /site/* appservers-grp1

The upside I can see here is that the version mapping can be changed
without touching Apache.

I haven't tried this but I've seen comments from people who have used
this that the handling of session cookies and URL rewriting can get


messy.


3. As above, but install everything as one big webapp and do the
dispatching internally within the application code, using a custom
classloader to simulate zones

This seems to be the most flexible and portable, but also strikes me as
a fair amount of work to create :-)


* actually, not for a bug, but to improve the load balancing - please email me if curious

--
David Crooke, Chief Technology Officer
Convio Inc. - the online partner for nonprofits
11921 N Mopac Expy, Austin TX 78759
Tel: (512) 652 2600 - Fax: (512) 652 2699







This e-mail, including any attachments, is a confidential business communication, and 
may contain information that is confidential, proprietary and/or privileged.  This 
e-mail is intended only for the individual(s) to whom it is addressed, and may not be 
saved, copied, printed, disclosed or used by anyone else.  If you are not the(an) 
intended recipient, please immediately delete this e-mail from your computer system 
and notify the sender.  Thank you.


--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]






--
David Crooke, Chief Technology Officer
Convio Inc. - the online partner for nonprofits
11921 N Mopac Expy, Austin TX 78759
Tel: (512) 652 2600 - Fax: (512) 652 2699




Reply via email to