# Server-Side Load Metrics

A major feature of mod_cluster is the ability to use server-side load metrics to determine how best to balance requests.

The `DynamicLoadBalanceFactorProvider` bean computes the load balance factor of a node from a defined set of load metrics.

    <bean name="DynamicLoadBalanceFactorProvider" class="org.jboss.modcluster.load.impl.DynamicLoadBalanceFactorProvider" mode="On Demand">
      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.web:service=LoadBalanceFactorProvider",exposedInterface=org.jboss.modcluster.load.impl.DynamicLoadBalanceFactorProviderMBean.class)</annotation>
      <constructor>
        <parameter>
          <set elementClass="org.jboss.modcluster.load.metric.LoadMetric">
            <inject bean="BusyConnectorsLoadMetric"/>
            <inject bean="HeapMemoryUsageLoadMetric"/>
          </set>
        </parameter>
      </constructor>
      <property name="history">9</property>
      <property name="decayFactor">2</property>
    </bean>

Load metrics can be configured with an associated weight and capacity.

The weight (default is 1) indicates the significance of a metric with respect to the other metrics. For example, a metric of weight 2 will have twice the impact on the overall load factor than a metric of weight 1.

The capacity of a metric serves 2 functions:

- To normalize the load values from each metric. In some load metrics, capacity is already reflected in the load values. The capacity of a metric should be configured such that 0 <= (load / capacity) >= 1.

- To favor some nodes over others. By setting the metric capacities to different values on each node, proxies will effectively favor nodes with higher capacities, since they will return smaller load values. This adds an interesting level of granularity to node weighting. Consider a cluster of two nodes, one with more memory, and a second with a faster CPU; and two metrics, one memory-based and the other CPU-based. In the memory-based metric, the first node would be given a higher load capacity than the second node. In a CPU-based metric, the second node would be given a higher load capacity than the first node.

Each load metric contributes a value to the overall load factor of a node. The load factors from each metric are aggregated according to their weights.

In general, the load factor contribution of given metric is: (load / capacity) * weight / total weight.

The DynamicLoadBalanceFactorProvider applies a time decay function to the loads returned by each metric. The aggregate load, with respect to previous load values, can be expressed by the following formula:

L = (L0 + L1/D + L2/D2 + L3/D3 + ... + LH/DH) * (1 + D + D2 + D3 + ... DH)

... or more concisely as:

L = (∑H i=0 Li/Di) * (∑H i=0 Di)

... where D = decayFactor, and H = history.

Setting history = 0 effectively disables the time decay function and only the current load for each metric will be considered in the load balance factor computation.

The mod_cluster load balancer expects the load factor to be an integer between 0 and 100, where 0 indicates max load and 100 indicates zero load. Therefore, the final load factor sent to the load balancer LFinal = 100 - (L * 100)

While you are free to write your own load metrics, the following LoadMetrics are available out of the box:

## Web Container metrics

### `ActiveSessionsLoadMetric`

- Requires an explicit capacity

- Uses `SessionLoadMetricSource` to query session managers

- Analogous to method=S in mod_jk

e.g.

    <bean name="ActiveSessionsLoadMetric" class="org.jboss.modcluster.load.metric.impl.ActiveSessionsLoadMetric" mode="On Demand">
      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.web:service=ActiveSessionsLoadMetric",exposedInterface=org.jboss.modcluster.load.metric.LoadMetricMBean.class)</annotation>
      <constructor>
        <parameter><inject bean="SessionLoadMetricSource"/></parameter>
      </constructor>
      <property name="capacity">1000</property>
    </bean>
    <bean name="SessionLoadMetricSource" class="org.jboss.modcluster.load.metric.impl.SessionLoadMetricSource" mode="On Demand">
      <constructor>
        <parameter class="javax.management.MBeanServer">
          <inject bean="JMXKernel" property="mbeanServer"/>
        </parameter>
      </constructor>
    </bean>

### `BusyConnectorsLoadMetric`

- Returns the percentage of connector threads from the thread pool that are busy servicing requests

- Uses `ThreadPoolLoadMetricSource` to query connector thread

- Analogous to method=B in mod_jk

e.g.

    <bean name="BusyConnectorsLoadMetric" class="org.jboss.modcluster.load.metric.impl.BusyConnectorsLoadMetric" mode="On Demand">
      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.web:service=BusyConnectorsLoadMetric",exposedInterface=org.jboss.modcluster.load.metric.LoadMetricMBean.class)</annotation>
      <constructor>
        <parameter><inject bean="ThreadPoolLoadMetricSource"/></parameter>
      </constructor>
    </bean>
    <bean name="ThreadPoolLoadMetricSource" class="org.jboss.modcluster.load.metric.impl.ThreadPoolLoadMetricSource" mode="On Demand">
      <constructor>
        <parameter class="javax.management.MBeanServer">
          <inject bean="JMXKernel" property="mbeanServer"/>
        </parameter>
      </constructor>
    </bean>

### `ReceiveTrafficLoadMetric`

- Returns the incoming request POST traffic in KB/sec (the application needs to read POST data)

- Requires an explicit capacity

- Uses `RequestProcessorLoadMetricSource` to query request processors

- Analogous to method=T in mod_jk

e.g.

    <bean name="ReceiveTrafficLoadMetric" class="org.jboss.modcluster.load.metric.impl.ReceiveTrafficLoadMetric" mode="On Demand">
      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.web:service=ReceiveTrafficLoadMetric",exposedInterface=org.jboss.modcluster.load.metric.LoadMetricMBean.class)</annotation>
      <constructor>
        <parameter class="org.jboss.modcluster.load.metric.impl.RequestProcessorLoadMetricSource">
          <inject bean="RequestProcessorLoadMetricSource"/>
        </parameter>
      </constructor>
      <property name="capacity">1024</property>
    </bean>
    <bean name="RequestProcessorLoadMetricSource" class="org.jboss.modcluster.load.metric.impl.RequestProcessorLoadMetricSource" mode="On Demand">
      <constructor>
        <parameter class="javax.management.MBeanServer">
          <inject bean="JMXKernel" property="mbeanServer"/>
        </parameter>
      </constructor>
    </bean>

### `SendTrafficLoadMetric`

- Returns the outgoing request traffic in KB/sec

- Requires an explicit capacity

- Uses `RequestProcessorLoadMetricSource` to query request processors

- Analogous to method=T in mod_jk

    <bean name="SendTrafficLoadMetric" class="org.jboss.modcluster.load.metric.impl.SendTrafficLoadMetric" mode="On Demand">
      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.web:service=SendTrafficLoadMetric",exposedInterface=org.jboss.modcluster.load.metric.LoadMetricMBean.class)</annotation>
      <constructor>
        <parameter class="org.jboss.modcluster.load.metric.impl.RequestProcessorLoadMetricSource">
          <inject bean="RequestProcessorLoadMetricSource"/>
        </parameter>
      </constructor>
      <property name="capacity">512</property>
    </bean>

### `RequestCountLoadMetric`

- Returns the number of requests/sec

- Requires an explicit capacity

- Uses `RequestProcessorLoadMetricSource` to query request processors

- Analogous to method=R in mod_jk

e.g.

    <bean name="RequestCountLoadMetric" class="org.jboss.modcluster.load.metric.impl.RequestCountLoadMetric" mode="On Demand">
      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.web:service=RequestCountLoadMetric",exposedInterface=org.jboss.modcluster.load.metric.LoadMetricMBean.class)</annotation>
      <constructor>
        <parameter class="org.jboss.modcluster.load.metric.impl.RequestProcessorLoadMetricSource">
          <inject bean="RequestProcessorLoadMetricSource"/>
        </parameter>
      </constructor>
      <property name="capacity">1000</property>
    </bean>

## System/JVM metrics

### `AverageSystemLoadMetric`

- Returns CPU load

- Requires Java 1.6+

- Uses `OperatingSystemLoadMetricSource` to generically read attributes

e.g.

    <bean name="AverageSystemLoadMetric" class="org.jboss.modcluster.load.metric.impl.AverageSystemLoadMetric" mode="On Demand">
      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.web:service=AverageSystemLoadMetric",exposedInterface=org.jboss.modcluster.load.metric.LoadMetricMBean.class)</annotation>
      <constructor>
        <parameter><inject bean="OperatingSystemLoadMetricSource"/></parameter>
      </constructor>
    </bean>
    <bean name="OperatingSystemLoadMetricSource" class="org.jboss.modcluster.load.metric.impl.OperatingSystemLoadMetricSource" mode="On Demand">
    </bean>

### `HeapMemoryUsageLoadMetric`

- Returns the heap memory usage as a percentage of max heap size

e.g.

    <bean name="HeapMemoryUsageLoadMetric" class="org.jboss.modcluster.load.metric.impl.HeapMemoryUsageLoadMetric" mode="On Demand">
      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.web:service=HeapMemoryUsageLoadMetric",exposedInterface=org.jboss.modcluster.load.metric.LoadMetricMBean.class)</annotation>
    </bean>

## Other metrics

### `ConnectionPoolUsageLoadMetric`

- Returns the percentage of connections from a connection pool that are in use

- Uses ConnectionPoolLoadMetricSource to query JCA connection pools

e.g.

    <bean name="ConnectionPoolUsageMetric" class="org.jboss.modcluster.load.metric.impl.ConnectionPoolUsageLoadMetric" mode="On Demand">
      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.web:service=ConnectionPoolUsageLoadMetric",exposedInterface=org.jboss.modcluster.load.metric.LoadMetricMBean.class)</annotation>
      <constructor>
        <parameter><inject bean="ConnectionPoolLoadMetricSource"/></parameter>
      </constructor>
    </bean>
    <bean name="ConnectionPoolLoadMetricSource" class="org.jboss.modcluster.load.metric.impl.ConnectionPoolLoadMetricSource" mode="On Demand">
      <constructor>
        <parameter class="javax.management.MBeanServer">
          <inject bean="JMXKernel" property="mbeanServer"/>
        </parameter>
      </constructor>
    </bean>