]> granicus.if.org Git - apache/blob - docs/manual/mod/mod_proxy_balancer.xml
Merge in APR[-util] macros from branches/trunk-buildconf-noapr
[apache] / docs / manual / mod / mod_proxy_balancer.xml
1 <?xml version="1.0"?>
2 <!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
3 <?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
4 <!-- $LastChangedRevision$ -->
5
6 <!--
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
13
14      http://www.apache.org/licenses/LICENSE-2.0
15
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.
21 -->
22
23 <modulesynopsis metafile="mod_proxy_balancer.xml.meta">
24
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>
30
31 <summary>
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>
35     <ul>
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>
40     </ul>
41     
42     <p>The Load balancing scheduler algorithm is not provided by this
43     module but from other ones such as:</p>
44     <ul>
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>
49     </ul>
50
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>
55
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
60       large.</p>
61     </note>
62 </summary>
63 <seealso><module>mod_proxy</module></seealso>
64
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>
73 </section>
74
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>
90 </section>
91
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:
97     </p>
98
99     <highlight language="config">
100 &lt;Proxy balancer://mycluster&gt;
101     BalancerMember http://192.168.1.50:80
102     BalancerMember http://192.168.1.51:80
103 &lt;/Proxy&gt;
104 ProxyPass        "/test" "balancer://mycluster"
105 ProxyPassReverse "/test" "balancer://mycluster"
106     </highlight>
107
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:
111     </p>
112
113     <highlight language="config">
114 Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
115 &lt;Proxy balancer://mycluster&gt;
116     BalancerMember http://192.168.1.50:80 route=1
117     BalancerMember http://192.168.1.51:80 route=2
118     ProxySet stickysession=ROUTEID
119 &lt;/Proxy&gt;
120 ProxyPass        "/test" "balancer://mycluster"
121 ProxyPassReverse "/test" "balancer://mycluster"
122     </highlight>
123 </section>
124
125 <section id="environment">
126     <title>Exported Environment Variables</title>
127     <p>At present there are 6 environment variables exported:</p>
128
129     <dl>
130     <!-- ============= BALANCER_SESSION_STICKY =============== -->
131     <dt><var><a name="balancer_session_sticky" id="balancer_session_sticky">BALANCER_SESSION_STICKY</a></var></dt>
132     <dd>
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>
135     </dd>
136
137     <!-- ============= BALANCER_SESSION_ROUTE ================ -->
138     <dt><var><a name="balancer_session_route" id="balancer_session_route">BALANCER_SESSION_ROUTE</a></var></dt>
139     <dd>
140     <p>This is assigned the <var>route</var> parsed from the current
141     request.</p>
142     </dd>
143
144     <!-- ============= BALANCER_NAME ========================= -->
145     <dt><var><a name="balancer_name" id="balancer_name">BALANCER_NAME</a></var></dt>
146     <dd>
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>
149     </dd>
150
151     <!-- ============= BALANCER_WORKER_NAME ================== -->
152     <dt><var><a name="balancer_worker_name" id="balancer_worker_name">BALANCER_WORKER_NAME</a></var></dt>
153     <dd>
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>
156     </dd>
157
158     <!-- ============= BALANCER_WORKER_ROUTE ================= -->
159     <dt><var><a name="balancer_worker_route" id="balancer_worker_route">BALANCER_WORKER_ROUTE</a></var></dt>
160     <dd>
161     <p>This is assigned the <var>route</var> of the worker that will be
162     used for the current request.</p>
163     </dd>
164
165     <!-- ============= BALANCER_ROUTE_CHANGED ================= -->
166     <dt><var><a name="balancer_route_changed" id="balancer_route_changed">BALANCER_ROUTE_CHANGED</a></var></dt>
167     <dd>
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>
173     </dd>
174     </dl>
175
176 </section>
177
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
185     mode.
186     </p>
187
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>
191
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 &lt;Location "/balancer-manager"&gt;
197     SetHandler balancer-manager
198     Require host example.com
199 &lt;/Location&gt;
200 </highlight>
201
202     <p>You can now access load balancer manager by using a Web browser
203     to access the page
204     <code>http://your.server.name/balancer-manager</code>. Please note
205     that only Balancers defined outside of <code>&lt;Location ...&gt;</code>
206     containers can be dynamically controlled by the Manager.</p>
207 </section>
208
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 &lt;Proxy balancer://mycluster&gt;
259     BalancerMember http://192.168.1.50:80 route=node1
260     BalancerMember http://192.168.1.51:80 route=node2
261 &lt;/Proxy&gt;
262     </highlight>
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>
265 </section>
266
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>
280     <dl>
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>
284     attribute.</dd>
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>
300     </dl>
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>
308 </section>
309
310 </modulesynopsis>