Bill Stoddard
2003-07-23 03:27:49 UTC
Here is some nasty nasty code but it works well enough for me to test
some ideas. I'll refine it as I have time.
Quick overview of the implementation:
This code uses a single optional hook, the load_balance hook, which is
defined by mod_proxy, implemented in mod_proxy_lb.c and is called by
ap_proxy_http_create_connection in proxy_http.c. The hook takes three
input arguments:
request_rec *r,
char *load_balancer_module_id,
r->unparsed_uri,
and returns a 'trylist'. The trylist contains pointers to a couple of
callback functions defined by the lb module identified by
'load_balancer_module_id'. One callback is to fetch an ip address
(actually a proxy_conn_t*) to use to route a request. The other callback
is to report a failure to establish a connection with that
proxy_conn_t). The trylist also contains a void * pointer to an opaque
datatype specific to a particular load_balancer module. I did it this
way to reduce unnecessary coupling between the load balancers and
mod_proxy/proxy_http.
mod_proxy_lb.c is a braindead round robin router. Hopefully it is
sufficient to demonstrate where I'm heading... Load balancer modules can
be arbitraily complex in how they decide to route requests.
To use...
1. apply the patch from directory modules/proxy
2. add mod_proxy_lb.c to your compile environment (compile it as
loadable module)
3. Update httpd.conf with something like this:
LoadModule proxy_lb_module modules/mod_proxy_lb.so
<IfModule mod_proxy_lb.c>
LBServerCluster cluster1 http://downstreamserver1:port
LBServerCluster cluster1 http://downstreamserver2:port
LBProxyPass /file500.html cluster1
LBProxyPass /snoop cluster1
</IfModule>
Where 'downstreamserver#' is the name of a backend system to route
requests to. 'cluster1' is the name of a logical group of backend
machines pointed to by LBProxyPass directives (which are coded exactly
like ProxyPass directives, except the 'real' name is replaced by a
symbol representing the backend cluster.)
If I send a request for /snoop, the request will be routed to the
servers defined in LBServerCluster in the order they appear in the
config file. Rerouting to the next server will only occur if either the
DNS lookup or connection establishment to the server fails. Simple
failure to find a resource on the target server will not cause a reroute.
My fingers are tired of typing so here is the patch. Comments welcome.
Bill
some ideas. I'll refine it as I have time.
Quick overview of the implementation:
This code uses a single optional hook, the load_balance hook, which is
defined by mod_proxy, implemented in mod_proxy_lb.c and is called by
ap_proxy_http_create_connection in proxy_http.c. The hook takes three
input arguments:
request_rec *r,
char *load_balancer_module_id,
r->unparsed_uri,
and returns a 'trylist'. The trylist contains pointers to a couple of
callback functions defined by the lb module identified by
'load_balancer_module_id'. One callback is to fetch an ip address
(actually a proxy_conn_t*) to use to route a request. The other callback
is to report a failure to establish a connection with that
proxy_conn_t). The trylist also contains a void * pointer to an opaque
datatype specific to a particular load_balancer module. I did it this
way to reduce unnecessary coupling between the load balancers and
mod_proxy/proxy_http.
mod_proxy_lb.c is a braindead round robin router. Hopefully it is
sufficient to demonstrate where I'm heading... Load balancer modules can
be arbitraily complex in how they decide to route requests.
To use...
1. apply the patch from directory modules/proxy
2. add mod_proxy_lb.c to your compile environment (compile it as
loadable module)
3. Update httpd.conf with something like this:
LoadModule proxy_lb_module modules/mod_proxy_lb.so
<IfModule mod_proxy_lb.c>
LBServerCluster cluster1 http://downstreamserver1:port
LBServerCluster cluster1 http://downstreamserver2:port
LBProxyPass /file500.html cluster1
LBProxyPass /snoop cluster1
</IfModule>
Where 'downstreamserver#' is the name of a backend system to route
requests to. 'cluster1' is the name of a logical group of backend
machines pointed to by LBProxyPass directives (which are coded exactly
like ProxyPass directives, except the 'real' name is replaced by a
symbol representing the backend cluster.)
If I send a request for /snoop, the request will be routed to the
servers defined in LBServerCluster in the order they appear in the
config file. Rerouting to the next server will only occur if either the
DNS lookup or connection establishment to the server fails. Simple
failure to find a resource on the target server will not cause a reroute.
My fingers are tired of typing so here is the patch. Comments welcome.
Bill