From 3c5a741b5516b4ef49eaae4738e01960c3215018 Mon Sep 17 00:00:00 2001 From: "William A. Rowe Jr" Date: Wed, 11 Aug 2004 22:52:46 +0000 Subject: [PATCH] Add proxy_balancer to proxy module, including config and capturing -I ../generators for the mod_status.h Submitted by: mturk git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@104608 13f79535-47bb-0310-9956-ffa450edef68 --- modules/proxy/config.m4 | 6 + modules/proxy/mod_proxy.dsp | 4 +- modules/proxy/mod_proxy_balancer.dsp | 136 ++++++++++++++++++ modules/proxy/proxy_balancer.c | 203 +++++++++++++++++++++++++++ 4 files changed, 347 insertions(+), 2 deletions(-) create mode 100644 modules/proxy/mod_proxy_balancer.dsp create mode 100644 modules/proxy/proxy_balancer.c diff --git a/modules/proxy/config.m4 b/modules/proxy/config.m4 index 5592290a30..7b3a59789e 100644 --- a/modules/proxy/config.m4 +++ b/modules/proxy/config.m4 @@ -17,6 +17,7 @@ proxy_connect_objs="proxy_connect.lo" proxy_ftp_objs="proxy_ftp.lo" proxy_http_objs="proxy_http.lo" proxy_ajp_objs="proxy_ajp.lo ajp_header.lo ajp_link.lo ajp_msg.lo" +proxy_balancer_objs="proxy_balancer.lo" case "$host" in *os2*) @@ -25,12 +26,17 @@ case "$host" in proxy_connect_objs="$proxy_connect_objs mod_proxy.la" proxy_ftp_objs="$proxy_ftp_objs mod_proxy.la" proxy_http_objs="$proxy_http_objs mod_proxy.la" + proxy_balancer_objs="$proxy_balancer_objs mod_proxy.la" ;; esac APACHE_MODULE(proxy_connect, Apache proxy CONNECT module, $proxy_connect_objs, , $proxy_mods_enable) APACHE_MODULE(proxy_ftp, Apache proxy FTP module, $proxy_ftp_objs, , $proxy_mods_enable) APACHE_MODULE(proxy_http, Apache proxy HTTP module, $proxy_http_objs, , $proxy_mods_enable) +APACHE_MODULE(proxy_balancer, Apache proxy BALANCER module, $proxy_balancer_objs, , $proxy_mods_enable) + +APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current/../generators]) + APACHE_MODULE(proxy_ajp, Apache proxy AJP module, $proxy_ajp_objs, , no) if test "$proxy_ajp_enable" != "no" -o "$enable_proxy_ajp" != "no"; then diff --git a/modules/proxy/mod_proxy.dsp b/modules/proxy/mod_proxy.dsp index 616e1d15bd..46d43cc393 100644 --- a/modules/proxy/mod_proxy.dsp +++ b/modules/proxy/mod_proxy.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c -# ADD CPP /nologo /MD /W3 /Zi /O2 /I "../ssl" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "PROXY_DECLARE_EXPORT" /Fd"Release\mod_proxy_src" /FD /c +# ADD CPP /nologo /MD /W3 /Zi /O2 /I "../ssl" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../generators" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "PROXY_DECLARE_EXPORT" /Fd"Release\mod_proxy_src" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "NDEBUG" @@ -69,7 +69,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c -# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../ssl" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "PROXY_DECLARE_EXPORT" /Fd"Debug\mod_proxy_src" /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../ssl" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../generators" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "PROXY_DECLARE_EXPORT" /Fd"Debug\mod_proxy_src" /FD /c # ADD BASE MTL /nologo /D "_DEBUG" /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "_DEBUG" diff --git a/modules/proxy/mod_proxy_balancer.dsp b/modules/proxy/mod_proxy_balancer.dsp new file mode 100644 index 0000000000..0bb82bc677 --- /dev/null +++ b/modules/proxy/mod_proxy_balancer.dsp @@ -0,0 +1,136 @@ +# Microsoft Developer Studio Project File - Name="mod_proxy_balancer" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_proxy_balancer - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_proxy_balancer.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_proxy_balancer.mak" CFG="mod_proxy_balancer - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_proxy_balancer - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_proxy_balancer - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_proxy_balancer - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /Zi /O2 /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_proxy_balancer_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /machine:I386 /out:"Release/mod_proxy_balancer.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy_balancer.so +# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_proxy_balancer.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy_balancer.so /opt:ref + +!ELSEIF "$(CFG)" == "mod_proxy_balancer - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_proxy_balancer_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_proxy_balancer.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy_balancer.so +# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_proxy_balancer.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy_balancer.so + +!ENDIF + +# Begin Target + +# Name "mod_proxy_balancer - Win32 Release" +# Name "mod_proxy_balancer - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\proxy_balancer.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter ".h" +# Begin Source File + +SOURCE=.\mod_proxy.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\build\win32\win32ver.awk + +!IF "$(CFG)" == "mod_proxy_balancer - Win32 Release" + +# PROP Ignore_Default_Tool 1 +# Begin Custom Build - Creating Version Resource +InputPath=..\..\build\win32\win32ver.awk + +".\mod_proxy_balancer.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + awk -f ../../build/win32/win32ver.awk mod_proxy_balancer.so "proxy_balancer_module for Apache" ../../include/ap_release.h > .\mod_proxy_balancer.rc + +# End Custom Build + +!ELSEIF "$(CFG)" == "mod_proxy_balancer - Win32 Debug" + +# PROP Ignore_Default_Tool 1 +# Begin Custom Build - Creating Version Resource +InputPath=..\..\build\win32\win32ver.awk + +".\mod_proxy_balancer.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + awk -f ../../build/win32/win32ver.awk mod_proxy_balancer.so "proxy_balancer_module for Apache" ../../include/ap_release.h > .\mod_proxy_balancer.rc + +# End Custom Build + +!ENDIF + +# End Source File +# End Target +# End Project diff --git a/modules/proxy/proxy_balancer.c b/modules/proxy/proxy_balancer.c new file mode 100644 index 0000000000..9d6d367f3e --- /dev/null +++ b/modules/proxy/proxy_balancer.c @@ -0,0 +1,203 @@ +/* Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* Load balancer module for Apache proxy */ + +#define CORE_PRIVATE + +#include "mod_proxy.h" +#include "ap_mpm.h" +#include "apr_version.h" + +module AP_MODULE_DECLARE_DATA proxy_balancer_module; + +#if APR_HAS_THREADS1 +#define PROXY_BALANCER_LOCK(b) apr_thread_mutex_lock((b)->mutex) +#define PROXY_BALANCER_UNLOCK(b) apr_thread_mutex_unlock((b)->mutex) +#else +#define PROXY_BALANCER_LOCK(b) APR_SUCCESS +#define PROXY_BALANCER_UNLOCK(b) APR_SUCCESS +#endif + +/* Retrieve the parameter with the given name */ +static char *get_path_param(apr_pool_t *pool, char *url, + const char *name) +{ + char *path = NULL; + + for (path = strstr(url, name); path; path = strstr(path + 1, name)) { + path += (strlen(name) + 1); + if (*path == '=') { + /* + * Session path was found, get it's value + */ + ++path; + if (strlen(path)) { + char *q; + path = apr_pstrdup(pool, path); + if ((q = strchr(path, '?'))) + *q = '\0'; + return path; + } + } + } + return NULL; +} + +static char *get_cookie_param(request_rec *r, const char *name) +{ + const char *cookies; + const char *start_cookie; + + if ((cookies = apr_table_get(r->headers_in, "Cookie"))) { + for (start_cookie = strstr(cookies, name); start_cookie; + start_cookie = strstr(start_cookie + 1, name)) { + if (start_cookie == cookies || + start_cookie[-1] == ';' || + start_cookie[-1] == ',' || + isspace(start_cookie[-1])) { + + start_cookie += strlen(name); + while(*start_cookie && isspace(*start_cookie)) + ++start_cookie; + if (*start_cookie == '=' && start_cookie[1]) { + /* + * Session cookie was found, get it's value + */ + char *end_cookie, *cookie; + ++start_cookie; + cookie = apr_pstrdup(r->pool, start_cookie); + if ((end_cookie = strchr(cookie, ';')) != NULL) + *end_cookie = '\0'; + if((end_cookie = strchr(cookie, ',')) != NULL) + *end_cookie = '\0'; + return cookie; + } + } + } + } + return NULL; +} + +static proxy_runtime_worker *find_route_worker(proxy_balancer *balancer, + const char *route) +{ + int i; + proxy_runtime_worker *worker = (proxy_runtime_worker *)balancer->workers->elts; + for (i = 0; i < balancer->workers->nelts; i++) { + if (worker->route && strcmp(worker->route, route) == 0) { + return worker; + } + worker++; + } + return NULL; +} + +static proxy_runtime_worker *find_session_route(proxy_balancer *balancer, + request_rec *r, + char **route, + char **url) +{ + if (!balancer->sticky) + return NULL; + /* Try to find the sticky route inside url */ + *route = get_path_param(r->pool, *url, balancer->sticky); + if (!*route) + *route = get_cookie_param(r, balancer->sticky); + if (*route) { + proxy_runtime_worker *worker = find_route_worker(balancer, *route); + /* TODO: make worker status codes */ + /* See if we have a redirection route */ + if (worker && worker->w->status < 2 && worker->redirect) + worker = find_route_worker(balancer, worker->redirect); + else + worker = NULL; + return worker; + } + else + return NULL; +} + +static int proxy_balancer_pre_request(proxy_worker **worker, + proxy_balancer **balancer, + request_rec *r, + proxy_server_conf *conf, char **url) +{ + int access_status = OK; + proxy_runtime_worker *runtime; + char *route; + apr_status_t rv; + + /* Spet 1: check if the url is for us */ + if (!(*balancer = ap_proxy_get_balancer(r->pool, conf, *url))) + return DECLINED; + + /* Step 2: find the session route */ + + runtime = find_session_route(*balancer, r, &route, url); + if (!runtime) { + if (route && (*balancer)->sticky_force) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "balancer: (%s). All workers in error state for route (%s)", + (*balancer)->name, route); + return HTTP_SERVICE_UNAVAILABLE; + } + } + /* Lock the LoadBalancer + * XXX: perhaps we need the process lock here + */ + if ((rv = PROXY_BALANCER_LOCK(*balancer)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, + "proxy_balancer_pre_request: lock"); + return DECLINED; + } + + PROXY_BALANCER_UNLOCK(*balancer); + + return access_status; +} + +static int proxy_balancer_post_request(proxy_worker *worker, + proxy_balancer *balancer, + request_rec *r, + proxy_server_conf *conf) +{ + int access_status; + if (!balancer) + access_status = DECLINED; + else { + + + access_status = OK; + } + + return access_status; +} + +static void ap_proxy_balancer_register_hook(apr_pool_t *p) +{ + proxy_hook_pre_request(proxy_balancer_pre_request, NULL, NULL, APR_HOOK_FIRST); + proxy_hook_post_request(proxy_balancer_post_request, NULL, NULL, APR_HOOK_FIRST); +} + +module AP_MODULE_DECLARE_DATA proxy_balancer_module = { + STANDARD20_MODULE_STUFF, + NULL, /* create per-directory config structure */ + NULL, /* merge per-directory config structures */ + NULL, /* create per-server config structure */ + NULL, /* merge per-server config structures */ + NULL, /* command apr_table_t */ + ap_proxy_balancer_register_hook /* register hooks */ +}; -- 2.50.1