Jk2 architecture

Definitions

  1. Engine. This is a tomcat instance, running in a java process. Each engine must have a unique ID, and can be reached by multiple protocols over multiple transports
  2. Worker. A worker is the object serving ( processing ) the request. It can either forward it to a servlet Engine, to another worker or generate content itself ( status ). The important worker is "ajp13" implementing a simple/fast RPC mechanism. 
  3. Channel. 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, which are not yet fully supported. 
  4. Endpoint. An endpoint represents an established connection between the web server and the java engine. The connection is reused, and multiple endpoints can exist and be active at the same time for one server/engine pair. 
  5. Logger. The logger reports jk errors and debug statements. The goal is to use the native server logging whenever possible. At this moment there is a single logger, in future we may be able to associate loggers with individual webapps. 
  6. Config. The config stores and manipulates parameters for each jk object. 
  7. Uri ( XXX is it a good name ? ). A uri stores a pattern that is used to match requests, and asociated properties. 
  8. UriMapper. This implements the matching of requests against uri patterns. 
  9. WorkerEnv. The central controller, it controls global properties and provides access to all other objects. 
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:
  1. The name is composed from the type and a local part, separated with a ':' ( example:  channel.unixsocket:/tmp/jk.socket )
  2. The 'type' consist of '.' and ascii characters.  It is mapped to a JMX 'domain'. 
  3. The local part consists of ascii characters  and .:/;  
    Note that '=,' are not currently allowed - a future version may support the jmx syntax by using quotes to separate the local part from the property and value ( in .properties mode we must use '=' to separate the value from type, local name and property name ).
  4. The property is a simple name, with no dots. 
  5. 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.

Configuration architecture

Jk2 is using a mechanism similar with JMX to manage all its configurable objects. Each component is controled by a "jk_bean" structure, containing pointers to the setAttribute/getAttribute functions.

The jk_config object abstracts the persistent repository of config informations. Most components/properties can be configured at runtime. A runtime change can be made either directly on the object, affecting the running instance only ( by directly calling the object method or setting the field ), or via jk_config, making it persistent.

The config API can be accessed using AJP14 messages, using a simple worker ( like the status worker ) or by any other mean.

Communication protocol

Jk2 supports multiple communication protocols ( RPC-style ) and multiple transports. In addition, each communication protocol supports multiple "APIs", or sets of functions that are supported.

The current protocol is called AJP13. It supports marshalling/unmarshalling of strings and ints, with minimal overhead.

The current API is also called ajp13. It consist of 5 methods:

 It is desirable to migrate to a standard protocol for encoding and RPC ( CDR, XDR, etc ), and to support additional protcols ( like WARP ). However the AJP13 protocol is stable and shouldn't change in future.

The ajp13 API is also stable and frozen. In future, what will be called 'ajp14' may provide additional functions. ( using the same name for API and protocol is very confusing, but that's what we have. We should at least call them consistently "ajp13 protocol" and "ajp13 api" )

Low level components

Jk2 uses a object oriented style, allowing multiple implementations for each object. The model is based on the style used in JNI ( and a bit Corba C bindings). Each function takes as parameter a pointer to an execution context ( jk_env ), a pointer to its own object structure, and the normal parameters.

Jk_env is not completed, but it'll support basic exception handling ( JNI style ), a local pool, etc.

In addition, each configurable component has as the first member a jk_bean pointer, pointing to the JMX-like dynamic configurator. The jk_env stores a table with all the known 'types', and a constructor for each.

Each object has a name, either specified explicitely or generated from it's type. The object name has the type as prefix. Jk_env also stores a table with all existing 'instances', by name.

It is assumed that all 'top level' objects will be long-lived ( including endpoints ).

Default configuration

Jk2 uses a config file ( jk2.conf ) in the style of a .properties or ini file. It can be configured to use any other backend that provides similar capabilities.

The default config file is user editable, but mod_jk will persist the changes requested by protocol. If you manually change the file while jk is working, your changes will be lost. The config file supports no comments at this moment. We'll allow a limited form of comments that can be persisted.

The default configuration format . . Each setting consists of an object name and a property, with the associated value. The property name is a simple string, with no '.' in it. The name can be anything, but it must have a known 'type' as prefix.

2 formats are supported:

TYPE:NAME.PROPERTY=VALUE 
and
[TYPE:NAME]
PROPERTY=VALUE

In addition to the configuration file, properties can be set from the main server config file - but those will not be modifiable.

Properties with no type prefix will be stored as 'global' properties.

The first time a name is found, the object will be created using the type prefix ( by looking for the longest match on all known types ).

Default values / guessing

Each component will do the best effort to detect it's environment and set default values, to minimze the user effort.

On startup, jk2 will set few global settings:

All those are either compile time or extracted from the running server, and can be used to construct other settings. A separate document defines all the supported properties and 'magic' that is used to automatically configure the object and simplify the config.

Source code structure 

Each interface "foo" is defined in a file include/jk_foo.h. If the interface has a single ( or base ) implementation, it'll be called common/jk_foo.c. If it has multiple implementations, the files will be named jk_foo_bar.c. All server-specific files are in server/[SERVER] ( server/apache2, etc ). The apache13 objects should be used as a basis for new servers, apache2 has a number of extra fancy features to be used as model for 'deeper' integration. The default set of types is defined in common/jk_registry.c, common/jk_registry.h. Additional types can be defined at runtime in the server adapter or various other components.

Limitations

The current implementations has a number of limitations that will be removed in a future version:

Issues