2 <!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
3 <?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
4 <!-- $LastChangedRevision$ -->
7 Licensed to the Apache Software Foundation (ASF) under one or more
8 contributor license agreements. See the NOTICE file distributed with
9 this work for additional information regarding copyright ownership.
10 The ASF licenses this file to You under the Apache License, Version 2.0
11 (the "License"); you may not use this file except in compliance with
12 the License. You may obtain a copy of the License at
14 http://www.apache.org/licenses/LICENSE-2.0
16 Unless required by applicable law or agreed to in writing, software
17 distributed under the License is distributed on an "AS IS" BASIS,
18 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 See the License for the specific language governing permissions and
20 limitations under the License.
23 <modulesynopsis metafile="mod_proxy_balancer.xml.meta">
25 <name>mod_proxy_balancer</name>
26 <description><module>mod_proxy</module> extension for load balancing </description>
27 <status>Extension</status>
28 <sourcefile>mod_proxy_balancer.c</sourcefile>
29 <identifier>proxy_balancer_module</identifier>
32 <p>This module <em>requires</em> the service of <module
33 >mod_proxy</module> and it provides load balancing for
34 all the supported protocols. The most important ones are:</p>
36 <li>HTTP, using <module>mod_proxy_http</module></li>
37 <li>FTP, using <module>mod_proxy_ftp</module></li>
38 <li>AJP13, using <module>mod_proxy_ajp</module></li>
39 <li>WebSocket, using <module>mod_proxy_wstunnel</module></li>
42 <p>The Load balancing scheduler algorithm is not provided by this
43 module but from other ones such as:</p>
45 <li><module>mod_lbmethod_byrequests</module></li>
46 <li><module>mod_lbmethod_bytraffic</module></li>
47 <li><module>mod_lbmethod_bybusyness</module></li>
48 <li><module>mod_lbmethod_heartbeat</module></li>
51 <p>Thus, in order to get the ability of load balancing,
52 <module>mod_proxy</module>, <module>mod_proxy_balancer</module>
53 and at least one of load balancing scheduler algorithm modules have
54 to be present in the server.</p>
56 <note type="warning"><title>Warning</title>
57 <p>Do not enable proxying until you have <a
58 href="mod_proxy.html#access">secured your server</a>. Open proxy
59 servers are dangerous both to your network and to the Internet at
63 <seealso><module>mod_proxy</module></seealso>
65 <section id="scheduler">
66 <title>Load balancer scheduler algorithm</title>
67 <p>At present, there are 3 load balancer scheduler algorithms available
68 for use: Request Counting, Weighted Traffic Counting and Pending Request
69 Counting. These are controlled via the <code>lbmethod</code> value of
70 the Balancer definition. See the <directive module="mod_proxy">ProxyPass</directive>
71 directive for more information, especially regarding how to
72 configure the Balancer and BalancerMembers.</p>
75 <section id="stickyness">
76 <title>Load balancer stickyness</title>
77 <p>The balancer supports stickyness. When a request is proxied
78 to some back-end, then all following requests from the same user
79 should be proxied to the same back-end. Many load balancers implement
80 this feature via a table that maps client IP addresses to back-ends.
81 This approach is transparent to clients and back-ends, but suffers
82 from some problems: unequal load distribution if clients are themselves
83 hidden behind proxies, stickyness errors when a client uses a dynamic
84 IP address that changes during a session and loss of stickyness, if the
85 mapping table overflows.</p>
86 <p>The module <module>mod_proxy_balancer</module> implements stickyness
87 on top of two alternative means: cookies and URL encoding. Providing the
88 cookie can be either done by the back-end or by the Apache web server
89 itself. The URL encoding is usually done on the back-end.</p>
92 <section id="example">
93 <title>Examples of a balancer configuration</title>
94 <p>Before we dive into the technical details, here's an example of
95 how you might use <module>mod_proxy_balancer</module> to provide
96 load balancing between two back-end servers:
99 <highlight language="config">
100 <Proxy balancer://mycluster>
101 BalancerMember http://192.168.1.50:80
102 BalancerMember http://192.168.1.51:80
104 ProxyPass "/test" "balancer://mycluster"
105 ProxyPassReverse "/test" "balancer://mycluster"
108 <p>Another example of how to provide load balancing with stickyness
109 using <module>mod_headers</module>, even if the back-end server does
110 not set a suitable session cookie:
113 <highlight language="config">
114 Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
115 <Proxy balancer://mycluster>
116 BalancerMember http://192.168.1.50:80 route=1
117 BalancerMember http://192.168.1.51:80 route=2
118 ProxySet stickysession=ROUTEID
120 ProxyPass "/test" "balancer://mycluster"
121 ProxyPassReverse "/test" "balancer://mycluster"
125 <section id="environment">
126 <title>Exported Environment Variables</title>
127 <p>At present there are 6 environment variables exported:</p>
130 <!-- ============= BALANCER_SESSION_STICKY =============== -->
131 <dt><var><a name="balancer_session_sticky" id="balancer_session_sticky">BALANCER_SESSION_STICKY</a></var></dt>
133 <p>This is assigned the <var>stickysession</var> value used for the current
134 request. It is the name of the cookie or request parameter used for sticky sessions</p>
137 <!-- ============= BALANCER_SESSION_ROUTE ================ -->
138 <dt><var><a name="balancer_session_route" id="balancer_session_route">BALANCER_SESSION_ROUTE</a></var></dt>
140 <p>This is assigned the <var>route</var> parsed from the current
144 <!-- ============= BALANCER_NAME ========================= -->
145 <dt><var><a name="balancer_name" id="balancer_name">BALANCER_NAME</a></var></dt>
147 <p>This is assigned the name of the balancer used for the current
148 request. The value is something like <code>balancer://foo</code>.</p>
151 <!-- ============= BALANCER_WORKER_NAME ================== -->
152 <dt><var><a name="balancer_worker_name" id="balancer_worker_name">BALANCER_WORKER_NAME</a></var></dt>
154 <p>This is assigned the name of the worker used for the current request.
155 The value is something like <code>http://hostA:1234</code>.</p>
158 <!-- ============= BALANCER_WORKER_ROUTE ================= -->
159 <dt><var><a name="balancer_worker_route" id="balancer_worker_route">BALANCER_WORKER_ROUTE</a></var></dt>
161 <p>This is assigned the <var>route</var> of the worker that will be
162 used for the current request.</p>
165 <!-- ============= BALANCER_ROUTE_CHANGED ================= -->
166 <dt><var><a name="balancer_route_changed" id="balancer_route_changed">BALANCER_ROUTE_CHANGED</a></var></dt>
168 <p>This is set to 1 if the session route does not match the
169 worker route (BALANCER_SESSION_ROUTE != BALANCER_WORKER_ROUTE) or the
170 session does not yet have an established route. This can be used to
171 determine when/if the client needs to be sent an updated route
172 when sticky sessions are used.</p>
178 <section id="balancer_manager">
179 <title>Enabling Balancer Manager Support</title>
180 <p>This module <em>requires</em> the service of
181 <module>mod_status</module>.
182 Balancer manager enables dynamic update of balancer
183 members. You can use balancer manager to change the balance
184 factor of a particular member, or put it in the off line
188 <p>Thus, in order to get the ability of load balancer management,
189 <module>mod_status</module> and <module>mod_proxy_balancer</module>
190 have to be present in the server.</p>
192 <p>To enable load balancer management for browsers from the example.com
193 domain add this code to your <code>httpd.conf</code>
194 configuration file</p>
195 <highlight language="config">
196 <Location "/balancer-manager">
197 SetHandler balancer-manager
198 Require host example.com
202 <p>You can now access load balancer manager by using a Web browser
204 <code>http://your.server.name/balancer-manager</code>. Please note
205 that only Balancers defined outside of <code><Location ...></code>
206 containers can be dynamically controlled by the Manager.</p>
209 <section id="stickyness_implementation">
210 <title>Details on load balancer stickyness</title>
211 <p>When using cookie based stickyness, you need to configure the
212 name of the cookie that contains the information about which back-end
213 to use. This is done via the <var>stickysession</var> attribute added
214 to either <directive module="mod_proxy">ProxyPass</directive> or
215 <directive module="mod_proxy">ProxySet</directive>. The name of
216 the cookie is case-sensitive. The balancer extracts the value of the
217 cookie and looks for a member worker with <var>route</var> equal
218 to that value. The <var>route</var> must also be set in either
219 <directive module="mod_proxy">ProxyPass</directive> or
220 <directive module="mod_proxy">ProxySet</directive>. The cookie can either
221 be set by the back-end, or as shown in the above
222 <a href="#example">example</a> by the Apache web server itself.</p>
223 <p>Some back-ends use a slightly different form of stickyness cookie,
224 for instance Apache Tomcat. Tomcat adds the name of the Tomcat instance
225 to the end of its session id cookie, separated with a dot (<code>.</code>)
226 from the session id. Thus if the Apache web server finds a dot in the value
227 of the stickyness cookie, it only uses the part behind the dot to search
228 for the route. In order to let Tomcat know about its instance name, you
229 need to set the attribute <code>jvmRoute</code> inside the Tomcat
230 configuration file <code>conf/server.xml</code> to the value of the
231 <var>route</var> of the worker that connects to the respective Tomcat.
232 The name of the session cookie used by Tomcat (and more generally by Java
233 web applications based on servlets) is <code>JSESSIONID</code>
234 (upper case) but can be configured to something else.</p>
235 <p>The second way of implementing stickyness is URL encoding.
236 The web server searches for a query parameter in the URL of the request.
237 The name of the parameter is specified again using <var>stickysession</var>.
238 The value of the parameter is used to lookup a member worker with <var>route</var>
239 equal to that value. Since it is not easy to extract and manipulate all
240 URL links contained in responses, generally the work of adding the parameters
241 to each link is done by the back-end generating the content.
242 In some cases it might be feasible doing
243 this via the web server using <module>mod_substitute</module> or
244 <module>mod_sed</module>. This can have negative impact on performance though.</p>
245 <p>The Java standards implement URL encoding slightly different. They use
246 a path info appended to the URL using a semicolon (<code>;</code>)
247 as the separator and add the session id behind. As in the cookie case,
248 Apache Tomcat can include the configured <code>jvmRoute</code> in this path
249 info. To let Apache find this sort of path info, you neet to set
250 <code>scolonpathdelim</code> to <code>On</code> in
251 <directive module="mod_proxy">ProxyPass</directive> or
252 <directive module="mod_proxy">ProxySet</directive>.</p>
253 <p>Finally you can support cookies and URL encoding at the same time, by
254 configuring the name of the cookie and the name of the URL parameter
255 separated by a vertical bar (<code>|</code>) as in the following example:</p>
256 <highlight language="config">
257 ProxyPass "/test" "balancer://mycluster" stickysession=JSESSIONID|jsessionid scolonpathdelim=On
258 <Proxy balancer://mycluster>
259 BalancerMember http://192.168.1.50:80 route=node1
260 BalancerMember http://192.168.1.51:80 route=node2
263 <p>If the cookie and the request parameter both provide routing information
264 for the same request, the information from the request parameter is used.</p>
267 <section id="stickyness_troubleshooting">
268 <title>Troubleshooting load balancer stickyness</title>
269 <p>If you experience stickyness errors, e.g. users lose their
270 application sessions and need to login again, you first want to
271 check whether this is because the back-ends are sometimes unavailable
272 or whether your configuration is wrong. To find out about possible
273 stability problems with the back-ends, check your Apache error log
274 for proxy error messages.</p>
275 <p>To verify your configuration, first check, whether the stickyness
276 is based on a cookie or on URL encoding. Next step would be logging
277 the appropriate data in the access log by using an enhanced
278 <directive module="mod_log_config">LogFormat</directive>.
279 The following fields are useful:</p>
281 <dt><code>%{MYCOOKIE}C</code></dt>
282 <dd>The value contained in the cookie with name <code>MYCOOKIE</code>.
283 The name should be the same given in the <var>stickysession</var>
285 <dt><code>%{Set-Cookie}o</code></dt>
286 <dd>This logs any cookie set by the back-end. You can track,
287 whether the back-end sets the session cookie you expect, and
288 to which value it is set.</dd>
289 <dt><code>%{BALANCER_SESSION_STICKY}e</code></dt>
290 <dd>The name of the cookie or request parameter used
291 to lookup the routing information.</dd>
292 <dt><code>%{BALANCER_SESSION_ROUTE}e</code></dt>
293 <dd>The route information found in the request.</dd>
294 <dt><code>%{BALANCER_WORKER_ROUTE}e</code></dt>
295 <dd>The route of the worker chosen.</dd>
296 <dt><code>%{BALANCER_ROUTE_CHANGED}e</code></dt>
297 <dd>Set to <code>1</code> if the route in the request
298 is different from the route of the worker, i.e.
299 the request couldn't be handled sticky.</dd>
301 <p>Common reasons for loss of session are session timeouts,
302 which are usually configurable on the back-end server.</p>
303 <p>The balancer also logs detailed information about handling
304 stickyness to the error log, if the log level is set to
305 <code>debug</code> or higher. This is an easy way to
306 troubleshoot stickyness problems, but the log volume might
307 be to high for production servers under high load.</p>