]> granicus.if.org Git - apache/commitdiff
Add proxy_balancer to proxy module, including config and capturing
authorWilliam A. Rowe Jr <wrowe@apache.org>
Wed, 11 Aug 2004 22:52:46 +0000 (22:52 +0000)
committerWilliam A. Rowe Jr <wrowe@apache.org>
Wed, 11 Aug 2004 22:52:46 +0000 (22:52 +0000)
-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
modules/proxy/mod_proxy.dsp
modules/proxy/mod_proxy_balancer.dsp [new file with mode: 0644]
modules/proxy/proxy_balancer.c [new file with mode: 0644]

index 5592290a30cfe674bd2f154853f89bd63feda0cc..7b3a59789e117cbd305b20a49aa91724daafc257 100644 (file)
@@ -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
index 616e1d15bd21445c26da1169968db1926d38ff84..46d43cc39353a3ed65a6a8d9bd3c612f2ea87486 100644 (file)
@@ -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 (file)
index 0000000..0bb82bc
--- /dev/null
@@ -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 (file)
index 0000000..9d6d367
--- /dev/null
@@ -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 */
+};