Tomcat Workers HowTo

# Tomcat workers.properties

By Gal Shachor `< shachor@il.ibm.com>`

A Tomcat worker is a Tomcat instance that is waiting to execute servlets on behalf of some web server. For example, we can have a web server such as Apache forwarding servlet requests to a Tomcat process (the worker) running behind it.

The scenario described above is a very simple one; in fact one can configure multiple Tomcat workers to serve servlets on behalf of a certain web server. The reasons for such configuration can be:

- We want different contexts to be served by different Tomcat workers to provide a development environment where all the developers share the same web server but own a Tomcat worker of their own.
- We want different virtual hosts served by different Tomcat processes to provide a clear separation between sites belonging to different companies.
- We want to provide load balancing, meaning run multiple Tomcat workers each on a machine of its own and distribute the requests between them.

There are probably more reasons for having multiple workers but I guess that this list is enough...

Tomcat workers are defined in a properties file dubbed workers.properties and this tutorial explains how to work with it.

## Defining Workers

Defining workers to the Tomcat web server plugin can be done using a properties file (a sample file named workers.properties is available in the conf/ directory); the file contains entries of the following form:

worker.list=<a comma separated list of worker names>

For example, `worker.list= ajp12, ajp13`

And

worker.<worker name>.<property>=<property value>

For example, `worker.local.port=8007`

When starting up, the web server plugin will instantiate the workers whose name appears in the worker.list property, these are also the workers to whom you can map requests.

Each named worker should also have a few entries to provide additional information on his behalf; this information includes the worker's type and other related worker information. Currently the following worker types that exists are (Tomcat 3.2-dev):

Worker type | Description
--- | ---
ajp12 | This worker knows how to forward requests to out-of-process Tomcat workers using the ajpv12 protocol.
ajp13 | This worker knows how to forward requests to out-of-process Tomcat workers using the ajpv13 protocol.
jni | This worker knows how to forward requests to in-process Tomcat workers using JNI.
lb | This is a load-balancing worker; it knows how to provide round-robin based sticky load balancing with a certain level of fault-tolerance.

Defining workers of a certain type should be done with the following property format:

worker.<worker name>.type=<worker type>

Where worker name is the name assigned to the worker and the worker type is one of the four types defined in the table (a worker name may not contain any space (a good naming convention for queue named should follow the Java variable naming rules).

For example:

Worker definition | Meaning
--- | ---
worker.local.type=ajp12 | Defines a worker named "local" that uses the ajpv12 protocol to forward requests to a Tomcat process.
worker.remote.type=ajp13 | Defines a worker named "remote" that uses the ajpv13 protocol to forward requests to a Tomcat process.
worker.fast.type=jni | Defines a worker named "fast" that uses JNI to forward requests to a Tomcat process.
worker.loadbalancer.type=lb | Defines a worker named "loadbalancer" that loadbalances several Tomcat processes transparently.

## Setting Worker Properties

After defining the workers you can also specify properties for them. Properties can be specified in the following manner:

worker.<worker name>.<property>=<property value>

Each worker has a set of properties that you can set as specified in the following subsections:

### ajp12 Worker properties

The ajp12 typed workers forward requests to out-of-process Tomcat workers using the ajpv12 protocol over TCP/IP sockets. The following table specifies properties that the ajp12 worker can accept:

Property name | Meaning | Example
--- | --- | ---
port | The port where the Tomcat worker is listening for ajp12 requests. | worker.local.port=8007
host | The host where the Tomcat worker is listening for ajp12 requests. | worker.local.host=www.x.com
lbfactor | When working with a load balancer worker, this is the load-balancing factor for the worker. (More on this in the lb worker section). | worker.local.lbfactor=2.5

### ajp13 Worker properties

The ajp13 typed workers forward requests to out-of-process Tomcat workers using the ajpv13 protocol over TCP/IP sockets. The main difference between ajpv12 and ajpv13 are that:

1. ajpv13 is a more binary protocol and it try to compress some of the request data by coding frequently used strings as small integers.
2. ajpv13 reuse open sockets and leaves them open for future requests.
3. ajpv13 has special treatment for SSL information so that the container can implement SSL related methods such as isSecure().

The following table specifies properties that the ajp13 worker can accept:

Property name | Meaning | Example
--- | --- | ---
port | The port where the Tomcat worker is listening for ajp13 requests. | worker.local13.port=8007
host | The host where the Tomcat worker is listening for ajp13 requests. | worker.local13.host=www.x.com
lbfactor | When working with a load balancer worker, this is the load-balancing factor for the worker. (More on this in the lb worker section). | worker.local13.lbfactor=2.5
cachesize | Specifies the number of open socket connections that the worker will keep. By default this value is 1, but multithreaded web servers such as Apach2.xx, IIS and Netscape will benefit the most by setting this value to a higher level (such as the estimated average concurrent users for Tomcat) | worker.local13.cachesize=30

### lb Worker properties

The load-balancing worker does not really communicate with Tomcat workers; instead it is responsible for the management of several "real" workers. This management includes:

- Instantiating the workers in the web server.
- Using the worker's load-balancing factor, perform weighed-round-robin load balancing where high lbfactor means stronger machine (that is going to handle more requests)
- Keeping requests belonging to the same session executing on the same Tomcat worker.
- Identifying failed Tomcat workers, suspending requests to them and instead fall-backing on other workers managed by the lb worker.

The overall result is that workers managed by the same lb worker are load-balanced (based on their lbfactor and current user session) and also fall-backed so a single Tomcat process death will not "kill" the entire site.

The following table specifies properties that the lb worker can accept:

Property name | Meaning | Example
--- | --- | ---
balanced_workers | A comma separated list of workers that the load balancer need to manage. These workers should not appear in the worker.list property. | worker.loadbalancer.balanced_workers= local13, local12

### jni Worker properties

The jni worker opens a JVM inside the web server process and executes Tomcat within it (that is in-process). Following that, messages to and from the JVM are passed using JNI method calls, this makes the jni worker faster then the out-of-process workers that need to communicate to the Tomcat workers by writing AJP messages over TCP/IP sockets.

Note: Since the JVM is multithreaded; the jni worker should be used only within multithreaded servers such as AOLServer, IIS, Netscape and Apache2.0. You should also make sure that the threading scheme used by the web servers match the one used to build the jk web server plugin.

Since the jni worker opens a JVM it can accept many properties that it forward to the JVM such as the classpath etc. as we can see in the following table.

Property name | Meaning | Example
--- | --- | ---
class_path | The classpath as used by the in-process JVM. This should point to all Tomcats' jar/file files as well as any class or other jar file that you want to add to the JVM. You should remember to also add Javac to the classpath. This can be done in Java2 by adding tools.jar to the classpath. In JDK1.xx you should just add classes.zip. The class_path property can be given in multiple lines. In this case the jk environment will concatenate all the classpath entries together by putting path delimiter (":"/";") between the entries. | worker.localjni.class_path=path-to-some-jarfile worker.localjni.class_path=path-to-class-directory
cmd_line | The command line that is handed over to Tomcats' startup code. The cmd_line property can be given in multiple lines. In this case the jk environment will concatenate all the cmd_line entries together by putting spaces between the entries. Note: The cmd_line string doesn't support embedded spaces. This is mostly likely to affect path specifications. On Windows, you can use the MS-DOS 8.3 name for directories that would otherwise contain a space. | worker.localjni.cmd_line=-config worker.localjni.cmd_line=path-to-tomcats-server.xml-file worker.localjni.cmd_line=-home worker.localjni.cmd_line=-path-to-tomcat-home
jvm_lib | Full path to the JVM implementation library. The jni worker will use this path to load the JVM dynamically. | worker.localjni.jvm_lib=full-path-to-jvm.dll
stdout | Full path to where the JVM write its System.out | worker.localjni.stdout=full-path-to-stdout-file
stderr | Full path to where the JVM write its System.err | worker.localjni.stderr=full-path-to-stderr-file
sysprops | Java system properties for the JVM | worker.localjni.sysprops=some-property
ld_path | Additional dynamic libraries path (similar in nature to LD_LIBRARY_PATH) | worker.localjni.ld_path=some-extra-dynamic-library-path

## Property file macros

Starting with Tomcat3.2 you can define "macros" in the property files. These macros let you define properties and later on use them while constructing other properties. For example the following fragment:

    workers.tomcat_home=c:\jakarta-tomcat
    workers.java_home=c:\jdk1.2.2
    ps=\
    worker.inprocess.class_path=$(workers.tomcat_home)$(ps)classes
    worker.inprocess.class_path=$(workers.java_home)$(ps)lib$(ps)tools.jar

Will end up with the following values for the worker.inprocess.class_path properties

    worker.inprocess.class_path= c:\jakarta-tomcat\classes
    worker.inprocess.class_path=c:\jdk1.2.2\lib\tools.jar

## The sample worker.properties

Since coping with worker.properties on your own is not an easy thing to do, a sample worker.properties file is bundled along with Tomcat3.2 (and above). The file is meant to be as generic as possible and it uses the property macros extensively.

The sample worker.properties contains the following high level definitions:

1. An ajp12 worker that used the host localhost and the port 8007
2. An ajp13 worker that used the host localhost and the port 8009
3. A jni worker
4. A lb worker that load balance the ajp12 and ajp13 workers

The ajp12, ajp13 and lb worker definitions can work without modifying the file. However to make the jni worker come into life you should set the following properties in the file:

- workers.tomcat_home - Have it point to your tomcat_home. E.g. wrkers.tomcat_home=c:\jakarta-tomcat
- workers.java_home - Have it point to where you placed your JDK. E.g. workers.java_home=c:\jdk1.2.2
- ps - Have it point to the file system separator of your OS. E.g. ps=\

When you are done, the default jni worker should work.