Apache Software Foundation | Jakarta Project | Apache Tomcat

## Components

Intro

Each component instance has a name, that is used for configuration and at runtime. Each component has a number of configurable properties. The following rules are used:

- The name is composed from the type and a local part, separated with a ':' ( example: channel.unixsocket:/tmp/jk.socket )
- The 'type' consist of '.' and ascii characters. It is mapped to a JMX 'domain'.
- The local part consists of ascii characters and .:/;
- The property is a simple name, with no dots.
- A simple form of substitution is used in values, where $(property) will be replaced with a previously defined setting. If the property has ':' in it, it'll take the value from the object, if not it'll take the value from a global map.

Common properties

Common properties for all components

Property name | Default | Description
disabled | 0 (false) | "disabled" state for the component, 1=true 0=false
debug | 0 (false) | Debug level for the component, 0=disabled, 1..10 enabled. Higher levels generate more debug information.
ver (short for, and formerly known as, version) | 0 | 'Generation' of the component config. Important for runtime reconfiguration. If you edit the config file or set the shmem properties, you need to also upgrade the version of the modified component. The config layer will detect the change and call the setter method.

workerEnv

This component represent the core jk2, it has the default logger for all other components. Is the central controller, it controls global properties and provides access to all other objects

Property name | Default | Description
logger | logger | Default loger used by jk2 components, can be changed in the config file, normally it defaults to "logger" the Alias for the default logger for the Server/platform.
sslEnable | 1 (true) | Enable handling of SSL
timing | 0 | Will jk2 get request timing (needs APR?)
forwardKeySize | not set | Enable filling of javax.servlet.request.key_size
forwardURICompat | set | Pass the URI untouched.
forwardURICompatUnparsed | not set | Parse the URI until the '?'.
forwardURIEscaped | not set | Pass the URI escaped.
noRecoveryIfRequestSent | set | No recovery in LB mode if a Tomcat allready received the request.
noRecoveryIfHeaderSent | set | No recovery in LB mode if a Tomcat allready start to send reply to client.

Only one of the forwardURI option could be used it replaces the default value.

config

The config component, hold the detail of the conifg system, such config file name, create global defines

Property name | Default | Description
file | ${serverRoot}/conf/workers2.properties | Location of the workers2.properties file
debug | 0 | Set the debug level of the config component
debugEnv | 0 | Set the debug level of the hidden env component

uriMap

shm

Shared memory descriptor

Property name | Default | Description
file | No default value | Name of the file that will be mmapped to use as shared memory, If set to 'anonymous' use the anonymous shered memory
size | No default value | Deprecated. Size of the file.
slots | 256 | Number of shared memory slots. Set to the number of child processes
useMemory | 0 | Use process memory instead of shared memory. Useful for single child mpm's

uri

A uri stores a pattern that is used to match requests to workers, and asociated properties

If the uri name doesn't have a slash then it is considered as a virtual host directive. Uri name can have a virtual host name and(or) port associated with. Format of such a name is hostname or hostname:port where hostname is virtual server name and the port is vitual server port number. The port number is used only for the non default server ports.

Special case is a default server named as [uri:*] that is used when the virtual host cannot be found inside the configuration. All the uri directives not containing host name belongs to this default server making global mappings.

Addition wild char scheme id [uri:*:port] that is used when you wish to match any virtual host having specified (non-default) port number, like [uri:*:443]. This will map all the virtual hosts no mather what is their name but that have port number 443.

The order how the host names are resolved is :

- Exact host name and optional non default port number
- Alias matching host name and port number
- *:port if the port is other then default
- Default server

Property name | Default | Description
group | lb:lb (The default loadbalancer) | Name of the tomcat group or worker that will process the request corresponding to the uri. This used to be called 'worker'
context |  | the context path for this uri component (webapp style).
servlet |  | Servlet path for this mapping
alias |  | server name alias. This setting should only be used for host uris like [uri:myHost:myPort] ( i.e. no /)

vm

Represents the JVM when used as inprocess container

Property name | Default | Description
JVM | (Autoguess) | JVM to use for this vm
OPT |  | Option to pass to this vm, this is a multivalued property
classpath |  | -Djava.class.path 0ption to pass to this vm, this is a multivalued property

channels

A channel represents a transport protocol, connecting 2 sides for RPC communication. The most common and standard is the tcp socket. Other important channels are unix socket and jni

channel.un

AF_UNIX socket. Only on UNIX like platform. These sockets are faster than "normal" sockets but they are limited to the machine.

Property name | Default | Description
file | Name of socket | Name of the socket file (It is created by the Tomcat ChannelUn)

channel.socket

Defines a communication transport to a remote Servlet Engine.

The name of the channels should be: channel.socket:HOST:PORT, where HOST and PORT are the tomcat Ajp location. You could use other names and explicitely set HOST and PORT, but this is discouraged. In most cases, you don't need to set any other config - just add a line like [channel.socket:localhost:8009] and all other things will have good defaults.

NB: Starting with JK2 2.0.4, APR is mandatory and the channel.socket use APR (previously called channel.apr).

Tomcat Engine must be set with jvmRoute="HOST:PORT", to match the default tomcatId of the channel.

Property name | Default | Description
port | extracted from the component name | Port where Tomcat is listening. It is automatically extracted from the name - you shouldn't have to specify it explicitely.
host | extracted from the component name | Remote host. You should use the name, no need to override it
graceful | 0 | If 1, only requests for existing sessions will be forwarded
keepalive | 0 | ?
timeout | 0 (infinite) | Socket timeout for sending and receiving
ndelay | 0 | If set to 1 Disables the Nagle algorithm for send coalescing
lb_factor | 1 | Load balancing factor to use. The lower the lb_factor the more often that tomcat will get requests but see "level" below.

level

1

Worker Priority. Valid values are 0-3. The functioning workers with the lowest level will be checked for the lowest lb_value, and if found will be run. The upper level workers are only checked upon failure of all workers on ALL of the levels below them. This is very useful for implementing failover withing a cluster. You could set the tomcat server local on the same machine as the apache instance to level 0 and all of the other workers to level 1. This would cause apache to only use the external tomcats when the local tomcat is down.

group | lb | loadbalanced groups to which this channel and the associated worker will be added, multivalued. You need to set it only if you have an advanced setup with multiple clusters.
tomcatId | Automatically set to the localname ( host:port ) | Must match the JVM route on tomcat the server.xml Engine element, for load balancing
route | Automatically set to the localname ( host:port ) | Same as tomcatId

channel.jni

The jni channel, used if tomcat is started inprocess

workers

For the moment 4 worker types are supported: worker.jni,ajp13,status,lb.

worker.jni

worker used in inprocess, holds the details of the Tomcat class to startup, and parameters to pass

There are two predefined jni workers onStartup and onShutdown . Those two workers are executed during startup and shutdown phase of the connector. Both must exists in the configuration to be able to start and shutdown Tomcat.

Property name | Default | Description
class | org/apache/jk/apr/TomcatStarter | class that holds the main method called to start tomcat
ARG |  | Arguments to pass to main method when called
stdout | NULL | file to redirect Standard output from the java process
stderr | NULL | file to redirect Standard output from the java process

ajp13

Default worker. If a property is in both the worker and the channel, you only need to define it in one place. The channel passes down the properties to its worker. (at least in the ajp13-channel.socket linkage)

Property name | Default | Description
secretkey | NULL | Magic: The secret key will be set automatically on the associated worker.
tomcatId | Automatically set to the localname ( host:port ) | Must match the JVM route on the tomcat server.xml Engine element, for load balancing
route | Automatically set to the localname ( host:port ) | Same as tomcatId
group | lb | loadbalanced groups to which this channel and the associated worker will be added, multivalued. You need to set it only if you have an advanced setup with multiple clusters.
lb_factor | 1 | Load balancing factor to use. The lower the lb_factor the more often that tomcat will get requests but see "level" below.

level

1

Worker Priority. Valid values are 0-3. The functioning workers with the lowest level will be checked for the lowest lb_value, and if found will be run. The upper level workers are only checked upon failure of all workers on ALL of the levels below them. This is very useful for implementing failover withing a cluster. You could set the tomcat server local on the same machine as the apache instance to level 0 and all of the other workers to level 1. This would cause apache to only use the external tomcats when the local tomcat is down.

channel |  | Communication channel used by the worker. Use the full name of the channel (everything between the []'s).
max_connections | 0 (unlimited) | Maximum number of currently used endpoints. If the specified number is reached then the load balancer has the chance to try another worker. This is very useful in situations when having multiple servers and you wish to finer grade the lb_factor.

connectTimeout

0 (no timeout)

With such timeout set, the web-server will send a CPING request just after physical connect to the remote Tomcat and will wait for a CPONG reply for the connectTimeout milliseconds, a guarantee that the remote Tomcat is not hang. Side effect, this round trip add a little delay at connection time and require a recent AJP13 implementation, with support for CPING/CPONG command.

replyTimeout | 0 (no timeout) | With such timeout set, the web-server will wait for Tomcat reply to a forwarded request for replyTimeout milliseconds. Another guarantee that the remote Tomcat is not hang. Warning, if you have 'normal' long running processes on Tomcat side, you shouldn't use this feature to avoid invalid errors reports or set the timeout accordingly.

prepostTimeout

0 (no timeout)

With such timeout set, the web-server will send a CPING request just before forwarding the request to the remote Tomcat and will wait for a CPONG reply for the prepostTimeout milliseconds, a guarantee that the remote Tomcat is not hang. Side effect, this round trip add a little delay in forwarding request and require a recent AJP13 implementation, with support for CPING/CPONG command.

status

An optional worker that outputs (HTML) pages with useful information to monitor JK2.

To create the worker, add a [status:] or [status:'a name'] section.

The status worker needs no 'local' name, although one can be used if desired.

To access the worker, add a [uri] section with the group= assigned to this worker.

The status worker has the following additional properties:

Property name | Default | Description
styleMode | 0 (None) | Defines if or how the status worker will apply a Style Sheet to returned pages.
stylePath | NULL | For styleMode=2 or 3, where to find the Style Sheet file.

The syleMode setting accepts the following values:

styleMode value | Description
0 | No Style settings are used. (Default)
1 | Use the built-in Default Style Sheet. It is presented as an 'Internal Style Sheet' to HTML pages.
2 | Use stylePath as a URI context to an external Style Sheet file to be returned by the Web Server.
3 | Use stylePath as a file-system reference to a Style Sheet file. It is presented as an 'Internal Style Sheet' to HTML pages.

If the stylePath has not been set, styleMode=2 and 3 are ignored.

The sylePath setting accepts the following values:

styleMode value | stylePath Description
2 | A URI context to a file (e.g /styles/jkstatus.css). It must begin with '/' and include the file name.
3 | A file-system path (suitable for the OS in use) plus file name. Also ${serverRoot}/conf/'file name' allows the file to be located in Apache's conf directory.

If the Style file cannot be found, Mode 2 and 3 record Apache log entries.

For styleMode=2 and 3, changes in the Style Sheet are effective on the next access to the status worker.

lb

Loadbalanced worker

Property name | Default | Description
worker |  |
noErrorHeader | 1 (true) | If set, jk2 won't touch the headers in case of error and will let for example Apache present the ErrorDocument via mod_alias.
noWorkerMsg |  |
noWorkerCode | 503 |
hwBalanceErr |  |

timeout

0 (disabled)

If all the workers are in the error state, probably by Tomcat refusing any new connections due to the overload, you can set the timeout forcing lb to wait that some worker becomes available, instead of immediately returning error to the client. This is very useful in situations with high peek load. The timeout should be set to the maximum application call time, but not less then 1 second.

attempts | 3 | Number of attempts that lb will try on each worker before giving up.
recovery | 60 (seconds) | Time to wait before retrying to see if the worker came out of the error state.
stickySession | 1 (true) | Sessions stick to the same worker, 1=true 0=false

loggers

Any connector based on jk2, at least has a default logger, that can be reached using the "logger" alias, the logger used is the more appropiate for the plataform/server combination, Apache2 under in any platform has logger.apache2 as default, IIS on his only platform uses logger.win32, and Any apache 1 install uses logger.file as default.., the config file lets you change that defaults, you can end using logger.file in IIs i.e

The properties shared by all loggers are:

Property name | Default | Description
level | INFO | Text of the log level. Strings supported: EMERG, ERROR, INFO, DEBUG

logger.file

Property name | Default | Description
file | ${serverRoot}/logs/jk2.log | Log file. XXX you may be able to change this at runtime, to implement rolling.

logger.win32

logger used in the IIS server by default, it ends at native Application Event Log.

logger.apache2

Logger used in Apache2 servers, it normally in ends in error.log

How Load Balancing Works

The lb_factor and level properties combine to deliver a flexible static load balancing solution. The level property is used to create up to four pools over workers in descending priority and lb_factor is used to weight the workers within a pool. The lower the level the more likely the worker is to be used and the lower the lb_factor the more likely the worker is to be used. Here is how the algorithm is currently implemented:

(Assume that every worker's lb_value is set to their lb_factor)

    if (loadbalancer has a route) and (stickysession=1){
        worker= loadbanlancer.getWorkerForRoute(route)
        if worker.hasRedirect
            redirect=worker.redirect
        else if !worker.hasError
            return worker
        }

    selectedWorker=null
    foreach lb_level {
        foreach worker in the level {
            if worker.isNotWorking
                continue
            if selectedWorker == null
                selectedWorker = worker
                continue
            if worker.lb_value < selectedWorker.lb_value
                selectedWorker = worker
                continue
        }
        if selectedWorker !=null
            break
    }

    Reenable workers in error state if the timeout has passed()

    if selectedWorker !=null {
        selectedWorker.lb_value += selectedWorker.lb_factor
        if selectedWorker.lb_value > 255 {
            foreach worker in load_balancer.workers[selectedWorker.level]
                worker.lb_value=worker.lb_factor
            }
        }
        return selectedWorker
    }