jk_lb_worker.c
来自「Tomcat 4.1与WebServer集成组件的源代码包.」· C语言 代码 · 共 627 行 · 第 1/2 页
C
627 行
/* ========================================================================= * * * * The Apache Software License, Version 1.1 * * * * Copyright (c) 1999-2001 The Apache Software Foundation. * * All rights reserved. * * * * ========================================================================= * * * * Redistribution and use in source and binary forms, with or without modi- * * fication, are permitted provided that the following conditions are met: * * * * 1. Redistributions of source code must retain the above copyright notice * * notice, this list of conditions and the following disclaimer. * * * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * * * 3. The end-user documentation included with the redistribution, if any, * * must include the following acknowlegement: * * * * "This product includes software developed by the Apache Software * * Foundation <http://www.apache.org/>." * * * * Alternately, this acknowlegement may appear in the software itself, if * * and wherever such third-party acknowlegements normally appear. * * * * 4. The names "The Jakarta Project", "Jk", and "Apache Software * * Foundation" must not be used to endorse or promote products derived * * from this software without prior written permission. For written * * permission, please contact <apache@apache.org>. * * * * 5. Products derived from this software may not be called "Apache" nor may * * "Apache" appear in their names without prior written permission of the * * Apache Software Foundation. * * * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES * * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * * THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY * * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * * POSSIBILITY OF SUCH DAMAGE. * * * * ========================================================================= * * * * This software consists of voluntary contributions made by many indivi- * * duals on behalf of the Apache Software Foundation. For more information * * on the Apache Software Foundation, please see <http://www.apache.org/>. * * * * ========================================================================= *//*************************************************************************** * Description: Load balancer worker, knows how to load balance among * * several workers. * * Author: Gal Shachor <shachor@il.ibm.com> * * Based on: * * Version: $Revision: 1.12 $ * ***************************************************************************/#include "jk_pool.h"#include "jk_service.h"#include "jk_util.h"#include "jk_worker.h"#include "jk_lb_worker.h"/* * The load balancing code in this *//* * Time to wait before retry... */#define WAIT_BEFORE_RECOVER (60*1) #define ADDITINAL_WAIT_LOAD (20)struct worker_record { char *name; double lb_factor; double lb_value; int is_local_worker; int in_error_state; int in_recovering; time_t error_time; jk_worker_t *w;};typedef struct worker_record worker_record_t;struct lb_worker { worker_record_t *lb_workers; unsigned num_of_workers; jk_pool_t p; jk_pool_atom_t buf[TINY_POOL_SIZE]; char *name; jk_worker_t worker; int in_local_worker_mode; int local_worker_only; int sticky_session;};typedef struct lb_worker lb_worker_t;struct lb_endpoint { jk_endpoint_t *e; lb_worker_t *worker; jk_endpoint_t endpoint;};typedef struct lb_endpoint lb_endpoint_t;/* ========================================================================= *//* Retrieve the parameter with the given name */static char *get_path_param(jk_ws_service_t *s, const char *name){ char *id_start = NULL; for(id_start = strstr(s->req_uri, name) ; id_start ; id_start = strstr(id_start + 1, name)) { if('=' == id_start[strlen(name)]) { /* * Session path-cookie was found, get it's value */ id_start += (1 + strlen(name)); if(strlen(id_start)) { char *id_end; id_start = jk_pool_strdup(s->pool, id_start); /* * The query string is not part of req_uri, however * to be on the safe side lets remove the trailing query * string if appended... */ if(id_end = strchr(id_start, '?')) { *id_end = '\0'; } return id_start; } } } return NULL;}/* ========================================================================= *//* Retrieve the cookie with the given name */static char *get_cookie(jk_ws_service_t *s, const char *name){ unsigned i; for(i = 0 ; i < s->num_headers ; i++) { if(0 == strcasecmp(s->headers_names[i], "cookie")) { char *id_start; for(id_start = strstr(s->headers_values[i], name) ; id_start ; id_start = strstr(id_start + 1, name)) { if('=' == id_start[strlen(name)]) { /* * Session cookie was found, get it's value */ id_start += (1 + strlen(name)); if(strlen(id_start)) { char *id_end; id_start = jk_pool_strdup(s->pool, id_start); if(id_end = strchr(id_start, ';')) { *id_end = '\0'; } return id_start; } } } } } return NULL;}/* ========================================================================= *//* Retrieve session id from the cookie or the parameter *//* (parameter first) */static char *get_sessionid(jk_ws_service_t *s){ char *val; val = get_path_param(s, JK_PATH_SESSION_IDENTIFIER); if(!val) { val = get_cookie(s, JK_SESSION_IDENTIFIER); } return val;}static char *get_session_route(jk_ws_service_t *s){ char *sessionid = get_sessionid(s); char *ch; if(!sessionid) { return NULL; } /* * Balance parameter is appended to the end */ ch = strrchr(sessionid, '.'); if(!ch) { return 0; } ch++; if(*ch == '\0') { return NULL; } return ch;}static void close_workers(lb_worker_t *p, int num_of_workers, jk_logger_t *l){ int i = 0; for(i = 0 ; i < num_of_workers ; i++) { p->lb_workers[i].w->destroy(&(p->lb_workers[i].w), l); }}static double get_max_lb(lb_worker_t *p) { unsigned i; double rc = 0.0; for(i = 0 ; i < p->num_of_workers ; i++) { if(!p->lb_workers[i].in_error_state) { if(p->lb_workers[i].lb_value > rc) { rc = p->lb_workers[i].lb_value; } } } return rc;}static worker_record_t *get_most_suitable_worker(lb_worker_t *p, jk_ws_service_t *s, int attempt){ worker_record_t *rc = NULL; double lb_min = 0.0; unsigned i; char *session_route = NULL; if (p->sticky_session) { session_route = get_session_route(s); } if(session_route) { for(i = 0 ; i < p->num_of_workers ; i++) { if(0 == strcmp(session_route, p->lb_workers[i].name)) { /* First attempt will allways be to the correct host. If this is indeed down and no hope of recovery, we'll go to fail-over */ if(attempt>0 && p->lb_workers[i].in_error_state) { break; } else { return &(p->lb_workers[i]); } } } } for(i = 0 ; i < p->num_of_workers ; i++) { if (!p->in_local_worker_mode || p->lb_workers[i].is_local_worker || !p->local_worker_only) { if(p->lb_workers[i].in_error_state) { if(!p->lb_workers[i].in_recovering) { time_t now = time(0); if((now - p->lb_workers[i].error_time) > WAIT_BEFORE_RECOVER) { p->lb_workers[i].in_recovering = JK_TRUE; p->lb_workers[i].error_time = now; rc = &(p->lb_workers[i]); break; } } } else { if(p->lb_workers[i].lb_value < lb_min || !rc) { lb_min = p->lb_workers[i].lb_value; rc = &(p->lb_workers[i]); if (rc->is_local_worker) break; } } } } if(rc && !rc->is_local_worker) { rc->lb_value += rc->lb_factor; } return rc;} static int JK_METHOD service(jk_endpoint_t *e, jk_ws_service_t *s, jk_logger_t *l, int *is_recoverable_error){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?