⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_proxy_balancer.c

📁 apache服务器源代码(版本号:2.2.2)
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright 1999-2005 The Apache Software Foundation or its licensors, as * applicable. * * 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"#include "apr_hooks.h"module AP_MODULE_DECLARE_DATA proxy_balancer_module;static int proxy_balancer_canon(request_rec *r, char *url){    char *host, *path, *search;    const char *err;    apr_port_t port = 0;    if (strncasecmp(url, "balancer:", 9) == 0) {        url += 9;    }    else {        return DECLINED;    }    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,             "proxy: BALANCER: canonicalising URL %s", url);    /* do syntatic check.     * We break the URL into host, port, path, search     */    err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);    if (err) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "error parsing URL %s: %s",                      url, err);        return HTTP_BAD_REQUEST;    }    /* now parse path/search args, according to rfc1738 */    /* N.B. if this isn't a true proxy request, then the URL _path_     * has already been decoded.  True proxy requests have r->uri     * == r->unparsed_uri, and no others have that property.     */    if (r->uri == r->unparsed_uri) {        search = strchr(url, '?');        if (search != NULL)            *(search++) = '\0';    }    else        search = r->args;    /* process path */    path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0, r->proxyreq);    if (path == NULL)        return HTTP_BAD_REQUEST;    r->filename = apr_pstrcat(r->pool, "proxy:balancer://", host,            "/", path, (search) ? "?" : "", (search) ? search : "", NULL);    return OK;}static int init_balancer_members(proxy_server_conf *conf, server_rec *s,                                 proxy_balancer *balancer){    int i;    proxy_worker *workers;    workers = (proxy_worker *)balancer->workers->elts;    for (i = 0; i < balancer->workers->nelts; i++) {        ap_proxy_initialize_worker_share(conf, workers, s);        ap_proxy_initialize_worker(workers, s);        ++workers;    }    workers = (proxy_worker *)balancer->workers->elts;    for (i = 0; i < balancer->workers->nelts; i++) {        /* Set to the original configuration */        workers[i].s->lbstatus = workers[i].s->lbfactor =          (workers[i].lbfactor ? workers[i].lbfactor : 1);    }    /* Set default number of attempts to the number of     * workers.     */    if (!balancer->max_attempts_set && balancer->workers->nelts > 1) {        balancer->max_attempts = balancer->workers->nelts - 1;        balancer->max_attempts_set = 1;    }    return 0;}/* Retrieve the parameter with the given name * Something like 'JSESSIONID=12345...N' */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);        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 = ap_strstr_c(cookies, name); start_cookie;             start_cookie = ap_strstr_c(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;}/* Find the worker that has the 'route' defined */static proxy_worker *find_route_worker(proxy_balancer *balancer,                                       const char *route){    int i;    proxy_worker *worker = (proxy_worker *)balancer->workers->elts;    for (i = 0; i < balancer->workers->nelts; i++) {        if (*(worker->s->route) && strcmp(worker->s->route, route) == 0) {            return worker;        }        worker++;    }    return NULL;}static proxy_worker *find_session_route(proxy_balancer *balancer,                                        request_rec *r,                                        char **route,                                        char **url){    proxy_worker *worker = NULL;    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);    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                            "proxy: BALANCER: Found value %s for "                            "stickysession %s", *route, balancer->sticky);    /*     * If we found a value for sticksession, find the first '.' within.     * Everything after '.' (if present) is our route.     */    if ((*route) && ((*route = strchr(*route, '.')) != NULL ))        (*route)++;    if ((*route) && (**route)) {        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                                  "proxy: BALANCER: Found route %s", *route);        /* We have a route in path or in cookie         * Find the worker that has this route defined.         */        worker = find_route_worker(balancer, *route);        if (worker && !PROXY_WORKER_IS_USABLE(worker)) {            /* We have a worker that is unusable.             * It can be in error or disabled, but in case             * it has a redirection set use that redirection worker.             * This enables to safely remove the member from the             * balancer. Of course you will need a some kind of             * session replication between those two remote.             */            if (*worker->s->redirect)                worker = find_route_worker(balancer, worker->s->redirect);            /* Check if the redirect worker is usable */            if (worker && !PROXY_WORKER_IS_USABLE(worker))                worker = NULL;        }        return worker;    }    else        return NULL;}static proxy_worker *find_best_worker(proxy_balancer *balancer,                                      request_rec *r){    proxy_worker *candidate = NULL;    if (PROXY_THREAD_LOCK(balancer) != APR_SUCCESS)        return NULL;    candidate = (*balancer->lbmethod->finder)(balancer, r);/*        PROXY_THREAD_UNLOCK(balancer);        return NULL;*/    PROXY_THREAD_UNLOCK(balancer);    if (candidate == NULL) {        /* All the workers are in error state or disabled.         * If the balancer has a timeout sleep for a while         * and try again to find the worker. The chances are         * that some other thread will release a connection.         * By default the timeout is not set, and the server         * returns SERVER_BUSY.         */#if APR_HAS_THREADS        if (balancer->timeout) {            /* XXX: This can perhaps be build using some             * smarter mechanism, like tread_cond.             * But since the statuses can came from             * different childs, use the provided algo.             */            apr_interval_time_t timeout = balancer->timeout;            apr_interval_time_t step, tval = 0;            /* Set the timeout to 0 so that we don't             * end in infinite loop             */            balancer->timeout = 0;            step = timeout / 100;            while (tval < timeout) {                apr_sleep(step);                /* Try again */                if ((candidate = find_best_worker(balancer, r)))                    break;                tval += step;            }            /* restore the timeout */            balancer->timeout = timeout;        }#endif    }    return candidate;}static int rewrite_url(request_rec *r, proxy_worker *worker,                        char **url){    const char *scheme = strstr(*url, "://");    const char *path = NULL;    if (scheme)        path = ap_strchr_c(scheme + 3, '/');    /* we break the URL into host, port, uri */    if (!worker) {        return ap_proxyerror(r, HTTP_BAD_REQUEST, apr_pstrcat(r->pool,                             "missing worker. URI cannot be parsed: ", *url,                             NULL));    }    *url = apr_pstrcat(r->pool, worker->name, path, NULL);    return OK;}static int proxy_balancer_pre_request(proxy_worker **worker,                                      proxy_balancer **balancer,                                      request_rec *r,                                      proxy_server_conf *conf, char **url){    int access_status;    proxy_worker *runtime;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -