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

📄 mod_proxy_balancer.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 4 页
字号:
        ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,        "proxy: BALANCER: (%s). Lock failed for find_best_worker()", balancer->name);        return NULL;    }    candidate = (*balancer->lbmethod->finder)(balancer, r);    if (candidate)        candidate->s->elected++;/*        PROXY_THREAD_UNLOCK(balancer);        return NULL;*/    if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,        "proxy: BALANCER: (%s). Unlock failed for find_best_worker()", balancer->name);    }    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 void force_recovery(proxy_balancer *balancer, server_rec *s){    int i;    int ok = 0;    proxy_worker *worker;    worker = (proxy_worker *)balancer->workers->elts;    for (i = 0; i < balancer->workers->nelts; i++, worker++) {        if (!(worker->s->status & PROXY_WORKER_IN_ERROR)) {            ok = 1;            break;            }    }    if (!ok) {        /* If all workers are in error state force the recovery.         */        worker = (proxy_worker *)balancer->workers->elts;        for (i = 0; i < balancer->workers->nelts; i++, worker++) {            ++worker->s->retries;            worker->s->status &= ~PROXY_WORKER_IN_ERROR;            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,                         "proxy: BALANCER: (%s). Forcing recovery for worker (%s)",                         balancer->name, worker->hostname);        }    }}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;    char *route = NULL;    char *sticky = NULL;    apr_status_t rv;    *worker = NULL;    /* Step 1: check if the url is for us     * The url we can handle starts with 'balancer://'     * If balancer is already provided skip the search     * for balancer, because this is failover attempt.     */    if (!*balancer &&        !(*balancer = ap_proxy_get_balancer(r->pool, conf, *url)))        return DECLINED;    /* Step 2: Lock the LoadBalancer     * XXX: perhaps we need the process lock here     */    if ((rv = PROXY_THREAD_LOCK(*balancer)) != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,                     "proxy: BALANCER: (%s). Lock failed for pre_request",                     (*balancer)->name);        return DECLINED;    }    /* Step 3: force recovery */    force_recovery(*balancer, r->server);    /* Step 4: find the session route */    runtime = find_session_route(*balancer, r, &route, &sticky, url);    if (runtime) {        int i, total_factor = 0;        proxy_worker *workers;        /* We have a sticky load balancer         * Update the workers status         * so that even session routes get         * into account.         */        workers = (proxy_worker *)(*balancer)->workers->elts;        for (i = 0; i < (*balancer)->workers->nelts; i++) {            /* Take into calculation only the workers that are             * not in error state or not disabled.             *             * TODO: Abstract the below, since this is dependent             *       on the LB implementation             */            if (PROXY_WORKER_IS_USABLE(workers)) {                workers->s->lbstatus += workers->s->lbfactor;                total_factor += workers->s->lbfactor;            }            workers++;        }        runtime->s->lbstatus -= total_factor;        runtime->s->elected++;        *worker = runtime;    }    else if (route && (*balancer)->sticky_force) {        int i, member_of = 0;        proxy_worker *workers;        /*         * We have a route provided that doesn't match the         * balancer name. See if the provider route is the         * member of the same balancer in which case return 503         */        workers = (proxy_worker *)(*balancer)->workers->elts;        for (i = 0; i < (*balancer)->workers->nelts; i++) {            if (*(workers->s->route) && strcmp(workers->s->route, route) == 0) {                member_of = 1;                break;            }            workers++;        }        if (member_of) {            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                         "proxy: BALANCER: (%s). All workers are in error state for route (%s)",                         (*balancer)->name, route);            if ((rv = PROXY_THREAD_UNLOCK(*balancer)) != APR_SUCCESS) {                ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,                             "proxy: BALANCER: (%s). Unlock failed for pre_request",                             (*balancer)->name);            }            return HTTP_SERVICE_UNAVAILABLE;        }    }    if ((rv = PROXY_THREAD_UNLOCK(*balancer)) != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,                     "proxy: BALANCER: (%s). Unlock failed for pre_request",                     (*balancer)->name);    }    if (!*worker) {        runtime = find_best_worker(*balancer, r);        if (!runtime) {            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                         "proxy: BALANCER: (%s). All workers are in error state",                         (*balancer)->name);            return HTTP_SERVICE_UNAVAILABLE;        }        if ((*balancer)->sticky && runtime) {            /*             * This balancer has sticky sessions and the client either has not             * supplied any routing information or all workers for this route             * including possible redirect and hotstandby workers are in error             * state, but we have found another working worker for this             * balancer where we can send the request. Thus notice that we have             * changed the route to the backend.             */            apr_table_setn(r->subprocess_env, "BALANCER_ROUTE_CHANGED", "1");        }        *worker = runtime;    }    (*worker)->s->busy++;    /* Add balancer/worker info to env. */    apr_table_setn(r->subprocess_env,                   "BALANCER_NAME", (*balancer)->name);    apr_table_setn(r->subprocess_env,                   "BALANCER_WORKER_NAME", (*worker)->name);    apr_table_setn(r->subprocess_env,                   "BALANCER_WORKER_ROUTE", (*worker)->s->route);    /* Rewrite the url from 'balancer://url'     * to the 'worker_scheme://worker_hostname[:worker_port]/url'     * This replaces the balancers fictional name with the     * real hostname of the elected worker.     */    access_status = rewrite_url(r, *worker, url);    /* Add the session route to request notes if present */    if (route) {        apr_table_setn(r->notes, "session-sticky", sticky);        apr_table_setn(r->notes, "session-route", route);        /* Add session info to env. */        apr_table_setn(r->subprocess_env,                       "BALANCER_SESSION_STICKY", sticky);        apr_table_setn(r->subprocess_env,                       "BALANCER_SESSION_ROUTE", route);    }    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                 "proxy: BALANCER (%s) worker (%s) rewritten to %s",                 (*balancer)->name, (*worker)->name, *url);    return access_status;}static int proxy_balancer_post_request(proxy_worker *worker,                                       proxy_balancer *balancer,                                       request_rec *r,                                       proxy_server_conf *conf){#if 0    apr_status_t rv;    if ((rv = PROXY_THREAD_LOCK(balancer)) != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,            "proxy: BALANCER: (%s). Lock failed for post_request",            balancer->name);        return HTTP_INTERNAL_SERVER_ERROR;    }    /* TODO: placeholder for post_request actions     */    if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,            "proxy: BALANCER: (%s). Unlock failed for post_request",            balancer->name);    }    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                 "proxy_balancer_post_request for (%s)", balancer->name);#endif    if (worker && worker->s->busy)        worker->s->busy--;    return OK;}static void recalc_factors(proxy_balancer *balancer){    int i;    proxy_worker *workers;    /* Recalculate lbfactors */    workers = (proxy_worker *)balancer->workers->elts;    /* Special case if there is only one worker it's     * load factor will always be 1     */    if (balancer->workers->nelts == 1) {        workers->s->lbstatus = workers->s->lbfactor = 1;        return;    }    for (i = 0; i < balancer->workers->nelts; i++) {        /* Update the status entries */        workers[i].s->lbstatus = workers[i].s->lbfactor;    }}/* post_config hook: */

⌨️ 快捷键说明

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