Skip Headers

Oracle® HTTP Server Administering a Standalone Deployment Based on Apache 2.0 10g Release 3 (10.1.3) B25777-01 |
| Home | Solution Area | Contents | Index

Previous | Next |

# A Load Balancing Using mod_oc4j

This chapter contains information about `mod_oc4j` load balancing, including metric-based load balancing. Topics include:

- Load Balancing Policies

- Load Balancing Parameters

- Metric-based Load Balancing

## A.1 Load Balancing Policies

This section contains information about load balancing policies that `mod_oc4j` supports:

- Random

- Round Robin

- Random with Local Affinity

- Round Robin with Local Affinity

- Random using Routing Weight

- Round Robin using Routing Weight

- Metric Based

- Metric Based with Local Affinity

### A.1.1 Random

`mod_oc4j` randomly selects an OC4J instance from a list of OC4J instances that are candidates to service a request.

### A.1.2 Round Robin

`mod_oc4j` randomly selects an OC4J instance from an ordered list of OC4J instances that are candidates to service a request. Other OC4J instances are selected from the ordered list in turn, until the initially selected server is selected again. This sequence is repeated. If a particular OC4J instance is stopped or is unavailable, then that instance is skipped (no attempt is made to select it) until it can be brought back in service.

### A.1.3 Random with Local Affinity

`mod_oc4j` randomly selects local OC4J processes to service requests. When no local OC4J processes are available, `mod_oc4j` randomly selects remote OC4J processes and gives them equal opportunity to be selected.

### A.1.4 Round Robin with Local Affinity

`mod_oc4j` routes all requests to local OC4J processes in a round robin manner. When no local processes are available, `mod_oc4j` routes requests equally to each OC4J process on different hosts.

### A.1.5 Random using Routing Weight

`mod_oc4j` distributes requests according to the routing weight configured for each host. One OC4J process is selected randomly from the OC4J processes on that host.

### A.1.6 Round Robin using Routing Weight

`mod_oc4j` distributes the total request load to OC4J processes on each host based on the routing weight configured to each host. `mod_oc4j` selects an OC4J process in round robin manner from the OC4J processes on that host.

### A.1.7 Metric Based

`mod_oc4j` routes requests based on run time metrics from OC4J processes that indicate how much load can be placed on the OC4J process.

### A.1.8 Metric Based with Local Affinity

`mod_oc4j` routes all requests to local OC4J processes based on the run time performance metrics of OC4J processes. When there are no local OC4J processes available, `mod_oc4j` routes requests to each OC4J process on different hosts as per their performance metrics only.

## A.2 Load Balancing Parameters

This section discusses the following load balancing parameters:

- Oc4jSelectMethod

- Oc4jRoutingWeight

### A.2.1 Oc4jSelectMethod

Selects an OC4J instance for load balancing.

Category | Value
--- | ---
Syntax | `Oc4jSelectMethod` `roundrobin | roundrobin:local | roundrobin:weighted | random | random:local | random:weighted | metric | metric:local`
Required | No
Default | If `Oc4jSelectMethod` is not specified, it defaults to "`Oc4jSelectMethod` `roundrobin`".
Example | `Oc4jSelecctMethod random:local` `Oc4jSelecctMethod metric`
Usage | `Oc4jSelectMethod` `random`: Selects an OC4J process according to "Random" load balancing policy. `Oc4jSelectMethod roundrobin:weighted`: Selects an OC4J process according to "Round Robin using Routing Weight" load balancing policy. `Oc4jSelecctMethod metric:local:` Selects an OC4J process according to "Metric Based with Local Affinity" load balancing policy.

This directive is only applicable to the base server for Oracle Application Server 10g Release 3 (10.1.3) and an error will be printed at startup if specified within a `VirtualHost` container.

### A.2.2 Oc4jRoutingWeight

Associates a request routing weight for each machine during load balancing. Weighted routing is a load balancing strategy that distributes requests according to a predefined value assigned to each machine based on the predicted ability to handle load.

Category | Value
--- | ---
Syntax | `Oc4jRoutingWeight` <node_name> <routing_weight>
Required | No
Default | It defaults to OC4J processes on all the nodes with routing weight as 1. If `Oc4jRoutingWeight` is specified, but some hosts are not specified, it defaults to OC4J processes on any non-specified node with routing weight as 1.
- Example | There are two hosts in an Oracle Application Server cluster: Host_A and Host_B. Each has Oracle HTTP Server and OC4J processes running on them.
      Oc4jSelectMethod random:local
      Oc4jRoutingWeight Host_A 3
      Oc4jRoutingWeight Host_B 2
- `Oc4jRoutingWeight` directives are ignored. `mod_oc4j` on Host_A randomly routes all requests to OC4J processes on Host_A, `mod_oc4j` on Host_B randomly routes all requests to OC4J processes on Host_B. There are four hosts in an Oracle Application Server cluster: Host_A, Host_B, Host_C, and Host_D. Each has Oracle HTTP Server and OC4J processes running on them.
      Oc4jSelectMethod roundrobin:weighted
      Oc4jRoutingWeight Host_A 3
      Oc4jRoutingWeight Host_B 2
- `mod_oc4j` on all the machines route three times the number of requests to OC4J processes running on Host_A, two times the number of requests on Host_B, one time the number of requests on Host_C, and one time the number of requests on Host_D in a round robin manner. There are four hosts in an Oracle Application Server cluster: Host_A, Host_B, Host_C, and Host_D. Each has Oracle HTTP Server and OC4J processes running on them.
      Oc4jSelectMethod roundrobin:weighted
`mod_oc4j` on all the machines route requests equally to OC4J processes on Host_A, Host_B, Host_C, and Host_D in a round robin manner.
Usage | `Oc4jRoutingWeight` is taken into account only when Oc4jSelectMethod specifies weighted. "`Oc4jRoutingWeight` <node_name> <routing_weight>" associates a request routing weight to each node. `node_name` can be in host name or IP address format. For hosts with multiple interfaces, if different interfaces are specified, it is assumed that they are different hosts.

This directive is only applicable to the base server for Oracle Application Server 10g Release 3 (10.1.3) and an error will be printed at startup if specified within a `VirtualHost` container.

## A.3 Metric-based Load Balancing

Metric-based load balancing is a way to distribute request load among OC4Js based on a "health" metric that each OC4J reports. The metric range is between 0 and 100, where 0 is very busy, or unhealthy, and 100 is not busy, or healthy. When metric-based load balancing is enabled, requests are distributed among OC4Js based on a ratio of a metric received for an individual OC4J, divided by the total of the metrics received from all the OC4Js.

For example, OC4J process p1 reports a metric of 20, process p2 reports a metric of 40, and process p3 reports a metric of 90. The requests would be distributed as follows:

- p1 is routed 20 out of every 150 requests (13%)

- p2 is routed 40 out of every 150 requests (27%)

- p3 is routed 90 out of every 150 requests (60%)

You must configure Oracle HTTP Server and OC4J to enable metric-based load balancing. The following sections contain the required configuration information:

- Configuring Oracle HTTP Server

- Configuring OC4J

### A.3.1 Configuring Oracle HTTP Server

On the Oracle HTTP Server side, specify "`Oc4jSelectMethod metric`" or "`Oc4jSelectMethod` `metric:local`" in mod_oc4j.conf.

See Also: "Oc4jSelectMethod" "Metric Based" "Metric Based with Local Affinity"

### A.3.2 Configuring OC4J

On the OC4J side, you must configure the metric collector in `ORACLE_HOME/``j2ee/home/config/server.xml` in UNIX or `ORACLE_HOME/``j2ee\home\config\server.xml` on Windows. Configuring the `<metric-collector>` element tells OC4J to start sending a metric to `mod_oc4j` so that `mod_oc4j` can make routing decisions to load balance incoming requests to a list of available OC4J instances.

The metric sent from OC4J to `mod_oc4j` is used only when metric-based load balancing is specified for `mod_oc4j` and when OC4J runs in an Oracle Application Server environment.

If you specify metric-based load balancing in `mod_oc4j` and do not specify the `<metric-collector>` element in `server.xml`, then `mod_oc4j` expects OC4J to send metrics, but OC4J does not send metrics. In this case, `mod_oc4j` reports the following warning message:

    No run time metrics for oc4j(opmnid=%s) in notification Oc4jSelectMethod is
    configured to use run time metrics, please make sure OC4J side is configured
    accordingly. Default to 50.

In this case, `mod_oc4j` uses the value "50" for each of the OC4J processes and continues.

Likewise, if you specify the `<metric-collector>` element in `server.xml`, but do not specify metric-based load balancing in `mod_oc4j`, then OC4J sends metrics but `mod_oc4j` is not configured to receive metrics. In this case, `mod_oc4j` ignores the metrics and uses whatever the configured method is for load balancing. You specify the load balancing method with Oc4jSelectMethod. If no `Oc4jSelectMethod` is specified, then `mod_oc4j` uses the default, which is roundrobin.

All OC4Js that are used from this Oracle HTTP Server instance must be configured identically. Otherwise, the number returned from the OC4Js will not be comparable and can produce some very poor load balancing results.

When `mod_oc4j` receives a notification containing the metrics information from OC4J, it immediately changes the request routing behavior. The default interval between notifications from OC4J is 30 seconds. This value can be configured using the system property `opmnPingInterval`, which is passed on the command line when OC4J is started by OPMN. To change the interval between notifications, specify the following in `opmn.xml` under the `OC4J <process-set>` configuration element:

    <module-data>
      <category id="start-parameters">
        <data id="java-options" value="-DopmnPingInterval=<new ping interval value>"/>
      </category>
    </module-data>

See Also: Oracle Process Manager and Notification Server Administrator's Guide

Specifying Metrics for OC4J

The following two methods can be used to specify metrics for OC4J:

- Configuring Metric-based Load Balancing to Use the DMSMetricCollector

- Building Your Own Metric Collector

#### A.3.2.1 Configuring Metric-based Load Balancing to Use the DMSMetricCollector

In this out of the box method, the `<metric-collector>` element takes a single attribute: `classname`. This attribute defines an interface for gathering and calculating a server-wide metric. Use `oracle.oc4j.server.DMSMetricCollector` for the `classname` attribute when using a DMS-based metric collector. A `DMSMetricCollector` instance takes several parameters.

The DMS metric is specified using the 'dms-noun' parameter, which is shown in the configuration example below. This is the metric on which the `DMSMetricCollector` bases its calculation. The recommended DMS metric for metric-based load balancing is `/oc4j/default/WEBS/processRequest.time`. This metric represents the processing time of the servlets in the default Web application.

The value sent to OC4J is a weighted average of the value computed based on the current DMS metric value, and the last value computed the last time a value was sent. The default weight is 0.7 for the current value, and 0.3 for the previous value. To modify the weights, one may set the "`history-proportion`" as shown the following example. This results in a weight of 0.8 for the current value and 0.2 for the previous value.

    <metric-collector classname="oracle.oc4j.server.DMSMetricCollector">
       <init-param>
         <param-name>
           dms-noun
         </param-name>
         <param-value>
           /oc4j/default/WEBs/processRequest.time
         </param-value>
       </init-param>
       <init-param>
         <param-name>
           history-proportion
         </param-name>
         <param-value>
           0.2
         </param-value>
       </init-param>
       <init-param>
         <param-name>
           debug
         </param-name>
         <param-value>
           false
         </param-value>
       </init-param>
    </metric-collector>

See Also: Oracle Application Server Performance Guide for a list of DMS metrics.

##### A.3.2.1.1 How DMS Metrics are Converted for Metric-based Load Balancing

When `getMetrics()` is called, the value of the DMS metric specified by the `dms-noun` parameter is obtained. The `delta` with the previous measurement is computed.

Since the scale is from 0 to 100, and the measurement is potentially unbounded, the following formula is applied:

    metric = 100 / (1 + (log (1 + delta)))

As outlined above, this metric should match the current situation, but also reflect on previous metric history. You can assign a weight of 1/3 to the previous history and 2/3 for the average just collected in order to form the new metric.

This new metric becomes the next metric's history, and factors in less and less as time passes. As shown in the configuration example, you can specify the proportion of the previous metric that enters in new metrics, by setting the `history-proportion` parameter to a floating point value between 0.0 and 1.0. Higher values mean that historical values matter more, making the metric less volatile. A lower value makes the metric reflect the most recent metric. The metric returned is as follows:

    smoothedmetric = ((1 - history-proportion) * metric) + (history-proportion * previousmetric)

The `smoothedmetric` is what is sent to `mod_oc4j` for load balancing purposes.

#### A.3.2.2 Building Your Own Metric Collector

You can implement the interface oracle.oc4j.api.MetricCollector to supply your own metric collector to `mod_oc4j`. The metric has to be between 0 and 100.

All metric collectors must implement the interface `oracle.oc4j.api.MetricCollector`. The concrete metric collector must have a constructor with no parameters so it can be instantiated.

The schema elements for the feature are in `server.xml`, and look like:

    <metric-collector classname="my.package.name.MyClassName">
      <init-param>
        <param-name>
          mysetting
        </param-name>
        <param-value>
          12345
        </param-value>
      </init-param>
    </metric-collector>

As per the preceding example, 0 or more parameters can be set on the metric collector, and are passed to it when `setParameters()` method is called. `setEnabled(true)` is called once after `setParameters()`. It signals the metric collector that it can begin gathering data as needed.

Note: If the custom metric collector starts threads, the threads need to be daemon threads. Otherwise they may prevent the server from shutting down in an orderly fashion.

After `oracle.oc4j.api.MetricCollector` has been implemented, package your metric in a jar file and add it to your library path, using the following, in `server.xml`:

    <library path="<path to>/mymetric.jar"/>

##### A.3.2.2.1 oracle.oc4j.api.MetricCollector

Here is the `oracle.oc4j.api.MetricCollector` interface:

    package oracle.oc4j.api;

     import java.util.Map;

     /**
      * Defines an interface for gathering and obtaining a server-wide metric.
      * The metric is used in iAS mode, by mod_oc4j, to load balance between
      * virtual oc4j instances.
      * The metric value is relative, and should be between 0 and 100, both
      * inclusive.
      * When configured for metric load balancing,
      * Mod_oc4j will route preferably to an oc4j with the greater value.
      * <p>Concrete instances of this class must have a public empty constructor in
      * order to be loaded and instantiated.
      */
     public interface MetricCollector {
       /**
        * Support for debugging: This is a property name to set to true in order
        * to display the metric that is sent from the server
        */
       String OC4J_METRIC_DEBUG_PROPERTY = "oc4j.metric.debug";

       /**
        * Debugging flag that depends on @{link #OC4J_METRIC_DEBUG_PROPERTY}
        */
       boolean DEBUG = Boolean.getBoolean( OC4J_METRIC_DEBUG_PROPERTY );

       /**
        * Initial metric to return when no measurement has been made (property key)
        */
       String OC4J_INITIAL_METRIC_PROPERTY = "oc4j.metric.initial";
       /**
        * Initial metric to return when no measurement has been made.
        * Default is 50
        */
       int INITIAL_METRIC = Integer.getInteger( OC4J_INITIAL_METRIC_PROPERTY, 50 ).intValue();

       /**
        * Enabled flag for the collector.
        * @return true if the collector is collecting data
        */
       boolean isEnabled();

       /**
        */
       void setEnabled( boolean enabled);

       /**
        * The parameters the metric collector is configured with.
        * This method will be called even when the set of parameters is null.
        * @param params the key/value pairs the metric collector is configured with,
        * or <code>null</code> if none
        */
       void setParameters( Map params );

       /**
        * @return a metric between 0 and 100, inclusive. 100 is better, 0 is worse
        */
       int getMetric();

     }