<?xml version="1.0"?>
<!-- $LastChangedRevision$ -->
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<modulesynopsis metafile="mod_lbmethod_byrequests.xml.meta">
<name>mod_lbmethod_byrequests</name>
<description>Request Counting load balancer scheduler algorithm for <module
>mod_proxy_balancer</module></description>
<status>Extension</status>
<identifier>lbmethod_byrequests_module</identifier>
<compatibility>Split off from <module>mod_proxy_balancer</module> in 2.3</compatibility>
<summary>
<p>This module does not provide any configuration directives of its own.
It requires the services of <module>mod_proxy_balancer</module>, and
provides the <code>byrequests</code> load balancing method..</p>
</summary>
<seealso><module>mod_proxy</module></seealso>
<seealso><module>mod_proxy_balancer</module></seealso>
<section id="requests">
<title>Request Counting Algorithm</title>
<p>Enabled via <code>lbmethod=byrequests</code>, the idea behind this
scheduler is that we distribute the requests among the
various workers to ensure that each gets their configured share
of the number of requests. It works as follows:</p>
<p><dfn>lbfactor</dfn> is <em>how much we expect this worker
to work</em>, or <em>the workers' work quota</em>. This is
a normalized value representing their "share" of the amount of
work to be done.</p>
<p><dfn>lbstatus</dfn> is <em>how urgent this worker has to work
to fulfill its quota of work</em>.</p>
<p>The <dfn>worker</dfn> is a member of the load balancer,
usually a remote host serving one of the supported protocols.</p>
<p>We distribute each worker's work quota to the worker, and then look
which of them needs to work most urgently (biggest lbstatus). This
worker is then selected for work, and its lbstatus reduced by the
total work quota we distributed to all workers. Thus the sum of all
lbstatus does not change(*) and we distribute the requests
as desired.</p>
<p>If some workers are disabled, the others will
still be scheduled correctly.</p>
<example><pre><code>for each worker in workers
worker lbstatus += worker lbfactor
total factor += worker lbfactor
if worker lbstatus > candidate lbstatus
candidate = worker
candidate lbstatus -= total factor</code></pre>
</example>
<p>If a balancer is configured as follows:</p>
<table style="data">
<tr><th>worker</th>
<th>a</th>
<th>b</th>
<th>c</th>
<th>d</th></tr>
<tr><th>lbfactor</th>
<td>25</td>
<td>25</td>
<td>25</td>
<td>25</td></tr>
<tr><th>lbstatus</th>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td></tr>
</table>
<p>And <var>b</var> gets disabled, the following schedule is produced:</p>
<table style="data">
<tr><th>worker</th>
<th>a</th>
<th>b</th>
<th>c</th>
<th>d</th></tr>
<tr><th>lbstatus</th>
<td><em>-50</em></td>
<td>0</td>
<td>25</td>
<td>25</td></tr>
<tr><th>lbstatus</th>
<td>-25</td>
<td>0</td>
<td><em>-25</em></td>
<td>50</td></tr>
<tr><th>lbstatus</th>
<td>0</td>
<td>0</td>
<td>0</td>
<td><em>0</em></td></tr>
<tr><td colspan="5">(repeat)</td></tr>
</table>
<p>That is it schedules: <var>a</var> <var>c</var> <var>d</var>
<var>a</var> <var>c</var> <var>d</var> <var>a</var> <var>c</var>
<var>d</var> ... Please note that:</p>
<table style="data">
<tr><th>worker</th>
<th>a</th>
<th>b</th>
<th>c</th>
<th>d</th></tr>
<tr><th>lbfactor</th>
<td>25</td>
<td>25</td>
<td>25</td>
<td>25</td></tr>
</table>
<p>Has the exact same behavior as:</p>
<table style="data">
<tr><th>worker</th>
<th>a</th>
<th>b</th>
<th>c</th>
<th>d</th></tr>
<tr><th>lbfactor</th>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td></tr>
</table>
<p>This is because all values of <dfn>lbfactor</dfn> are normalized
with respect to the others. For:</p>
<table style="data">
<tr><th>worker</th>
<th>a</th>
<th>b</th>
<th>c</th></tr>
<tr><th>lbfactor</th>
<td>1</td>
<td>4</td>
<td>1</td></tr>
</table>
<p>worker <var>b</var> will, on average, get 4 times the requests
that <var>a</var> and <var>c</var> will.</p>
<p>The following asymmetric configuration works as one would expect:</p>
<table style="data">
<tr><th>worker</th>
<th>a</th>
<th>b</th></tr>
<tr><th>lbfactor</th>
<td>70</td>
<td>30</td></tr>
<tr><td colspan="2"> </td></tr>
<tr><th>lbstatus</th>
<td><em>-30</em></td>
<td>30</td></tr>
<tr><th>lbstatus</th>
<td>40</td>
<td><em>-40</em></td></tr>
<tr><th>lbstatus</th>
<td><em>10</em></td>
<td>-10</td></tr>
<tr><th>lbstatus</th>
<td><em>-20</em></td>
<td>20</td></tr>
<tr><th>lbstatus</th>
<td><em>-50</em></td>
<td>50</td></tr>
<tr><th>lbstatus</th>
<td>20</td>
<td><em>-20</em></td></tr>
<tr><th>lbstatus</th>
<td><em>-10</em></td>
<td>10</td></tr>
<tr><th>lbstatus</th>
<td><em>-40</em></td>
<td>40</td></tr>
<tr><th>lbstatus</th>
<td>30</td>
<td><em>-30</em></td></tr>
<tr><th>lbstatus</th>
<td><em>0</em></td>
<td>0</td></tr>
<tr><td colspan="3">(repeat)</td></tr>
</table>
<p>That is after 10 schedules, the schedule repeats and 7 <var>a</var>
are selected with 3 <var>b</var> interspersed.</p>
</section>
</modulesynopsis>