Author: rjung Date: Thu Sep 22 23:23:18 2011 New Revision: 1174449 URL: http://svn.apache.org/viewvc?rev=1174449&view=rev Log: Add the mapping rule extension "stateless" and analogous HTTPD env var JK_STATELESS.
They can be used to improve session based load balancing. We normally count any request without session id as a new session. Requests known to not create a new session can be marked using "stateless". They will not influence the session balancing. Those requests themselves will be distributed in a round-robin way (but stickyness would be respected). Modified: tomcat/jk/trunk/native/apache-1.3/mod_jk.c tomcat/jk/trunk/native/apache-2.0/mod_jk.c tomcat/jk/trunk/native/common/jk_lb_worker.c tomcat/jk/trunk/native/common/jk_service.h tomcat/jk/trunk/native/common/jk_status.c tomcat/jk/trunk/native/common/jk_uri_worker_map.c tomcat/jk/trunk/native/common/jk_uri_worker_map.h tomcat/jk/trunk/native/common/jk_util.c tomcat/jk/trunk/native/iis/jk_isapi_plugin.c tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml tomcat/jk/trunk/xdocs/reference/apache.xml tomcat/jk/trunk/xdocs/reference/uriworkermap.xml tomcat/jk/trunk/xdocs/reference/workers.xml Modified: tomcat/jk/trunk/native/apache-1.3/mod_jk.c URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/apache-1.3/mod_jk.c?rev=1174449&r1=1174448&r2=1174449&view=diff ============================================================================== --- tomcat/jk/trunk/native/apache-1.3/mod_jk.c (original) +++ tomcat/jk/trunk/native/apache-1.3/mod_jk.c Thu Sep 22 23:23:18 2011 @@ -80,6 +80,7 @@ #define JK_ENV_CERTCHAIN_PREFIX ("SSL_CLIENT_CERT_CHAIN_") #define JK_ENV_REPLY_TIMEOUT ("JK_REPLY_TIMEOUT") #define JK_ENV_STICKY_IGNORE ("JK_STICKY_IGNORE") +#define JK_ENV_STATELESS ("JK_STATELESS") #define JK_ENV_WORKER_NAME ("JK_WORKER_NAME") #define JK_NOTE_WORKER_NAME ("JK_WORKER_NAME") #define JK_NOTE_WORKER_TYPE ("JK_WORKER_TYPE") @@ -681,6 +682,7 @@ static int init_ws_service(apache_privat char *ssl_temp = NULL; const char *reply_timeout = NULL; const char *sticky_ignore = NULL; + const char *stateless = NULL; rule_extension_t *e; /* Copy in function pointers (which are really methods) */ @@ -729,6 +731,7 @@ static int init_ws_service(apache_privat if (e) { s->extension.reply_timeout = e->reply_timeout; s->extension.sticky_ignore = e->sticky_ignore; + s->extension.stateless = e->stateless; s->extension.use_server_error_pages = e->use_server_error_pages; if (e->activation) { s->extension.activation = ap_palloc(r->pool, e->activation_size * sizeof(int)); @@ -763,6 +766,22 @@ static int init_ws_service(apache_privat } } + stateless = ap_table_get(r->subprocess_env, JK_ENV_STATELESS); + if (stateless) { + if (*stateless == '\0') { + s->extension.stateless = JK_TRUE; + } + else { + int r = atoi(stateless); + if (r) { + s->extension.stateless = JK_TRUE; + } + else { + s->extension.stateless = JK_FALSE; + } + } + } + if (conf->options & JK_OPT_DISABLEREUSE) s->disable_reuse = 1; Modified: tomcat/jk/trunk/native/apache-2.0/mod_jk.c URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/apache-2.0/mod_jk.c?rev=1174449&r1=1174448&r2=1174449&view=diff ============================================================================== --- tomcat/jk/trunk/native/apache-2.0/mod_jk.c (original) +++ tomcat/jk/trunk/native/apache-2.0/mod_jk.c Thu Sep 22 23:23:18 2011 @@ -115,6 +115,7 @@ #define JK_ENV_CERTCHAIN_PREFIX ("SSL_CLIENT_CERT_CHAIN_") #define JK_ENV_REPLY_TIMEOUT ("JK_REPLY_TIMEOUT") #define JK_ENV_STICKY_IGNORE ("JK_STICKY_IGNORE") +#define JK_ENV_STATELESS ("JK_STATELESS") #define JK_ENV_WORKER_NAME ("JK_WORKER_NAME") #define JK_NOTE_WORKER_NAME ("JK_WORKER_NAME") #define JK_NOTE_WORKER_TYPE ("JK_WORKER_TYPE") @@ -736,6 +737,7 @@ static int init_ws_service(apache_privat char *ssl_temp = NULL; const char *reply_timeout = NULL; const char *sticky_ignore = NULL; + const char *stateless = NULL; rule_extension_t *e; /* Copy in function pointers (which are really methods) */ @@ -783,6 +785,7 @@ static int init_ws_service(apache_privat if (e) { s->extension.reply_timeout = e->reply_timeout; s->extension.sticky_ignore = e->sticky_ignore; + s->extension.stateless = e->stateless; s->extension.use_server_error_pages = e->use_server_error_pages; if (e->activation) { s->extension.activation = apr_palloc(r->pool, e->activation_size * sizeof(int)); @@ -817,6 +820,22 @@ static int init_ws_service(apache_privat } } + stateless = apr_table_get(r->subprocess_env, JK_ENV_STATELESS); + if (stateless) { + if (*stateless == '\0') { + s->extension.stateless = JK_TRUE; + } + else { + int r = atoi(stateless); + if (r) { + s->extension.stateless = JK_TRUE; + } + else { + s->extension.stateless = JK_FALSE; + } + } + } + if (conf->options & JK_OPT_DISABLEREUSE) s->disable_reuse = 1; Modified: tomcat/jk/trunk/native/common/jk_lb_worker.c URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_lb_worker.c?rev=1174449&r1=1174448&r2=1174449&view=diff ============================================================================== --- tomcat/jk/trunk/native/common/jk_lb_worker.c (original) +++ tomcat/jk/trunk/native/common/jk_lb_worker.c Thu Sep 22 23:23:18 2011 @@ -807,8 +807,9 @@ static int find_best_byvalue(jk_ws_servi */ if (JK_WORKER_USABLE(states[wr.i], activation)) { if (candidate < 0 || wr.distance < d || - (wr.s->lb_value < curmin && - wr.distance == d)) { + (s->extension.stateless != JK_TRUE && + wr.s->lb_value < curmin && + wr.distance == d)) { candidate = i; curmin = wr.s->lb_value; d = wr.distance; @@ -1244,10 +1245,11 @@ static int JK_METHOD service(jk_endpoint if (p->worker->lbmethod == JK_LB_METHOD_REQUESTS || p->worker->lbmethod == JK_LB_METHOD_BUSYNESS || (!sessionid && + s->extension.stateless != JK_TRUE && (p->worker->lbmethod == JK_LB_METHOD_SESSIONS || p->worker->lbmethod == JK_LB_METHOD_NEXT))) rec->s->lb_value += rec->lb_mult; - if (!sessionid) { + if (!sessionid && s->extension.stateless != JK_TRUE) { rec->s->sessions++; } if (p->worker->lblock == JK_LB_LOCK_PESSIMISTIC) Modified: tomcat/jk/trunk/native/common/jk_service.h URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_service.h?rev=1174449&r1=1174448&r2=1174449&view=diff ============================================================================== --- tomcat/jk/trunk/native/common/jk_service.h (original) +++ tomcat/jk/trunk/native/common/jk_service.h Thu Sep 22 23:23:18 2011 @@ -84,6 +84,9 @@ struct svc_extension int reply_timeout; /* Whether to ignore session routing info */ int sticky_ignore; + /* Whether the request is stateless and should not + * influence session load balancing */ + int stateless; /* activation state overwrites for load balancers */ /* Dynamically allocated array with one entry per lb member. */ int *activation; Modified: tomcat/jk/trunk/native/common/jk_status.c URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_status.c?rev=1174449&r1=1174448&r2=1174449&view=diff ============================================================================== --- tomcat/jk/trunk/native/common/jk_status.c (original) +++ tomcat/jk/trunk/native/common/jk_status.c Thu Sep 22 23:23:18 2011 @@ -1551,6 +1551,7 @@ static void display_map(jk_ws_service_t uri_worker_map_get_source(uwr, l), uwr->extensions.reply_timeout, uwr->extensions.sticky_ignore, + uwr->extensions.stateless, uwr->extensions.fail_on_status_str ? uwr->extensions.fail_on_status_str : "-", uwr->extensions.active ? uwr->extensions.active : "-", uwr->extensions.disabled ? uwr->extensions.disabled : "-", @@ -1563,6 +1564,7 @@ static void display_map(jk_ws_service_t uri_worker_map_get_source(uwr, l), uwr->extensions.reply_timeout, uwr->extensions.sticky_ignore, + uwr->extensions.stateless, uwr->extensions.fail_on_status_str ? uwr->extensions.fail_on_status_str : "-", uwr->extensions.active ? uwr->extensions.active : "-", uwr->extensions.disabled ? uwr->extensions.disabled : "-", @@ -1579,6 +1581,7 @@ static void display_map(jk_ws_service_t jk_print_xml_att_string(s, 8, "source", uri_worker_map_get_source(uwr, l)); jk_print_xml_att_int(s, 8, "reply_timeout", uwr->extensions.reply_timeout); jk_print_xml_att_int(s, 8, "sticky_ignore", uwr->extensions.sticky_ignore); + jk_print_xml_att_int(s, 8, "stateless", uwr->extensions.stateless); jk_print_xml_att_string(s, 8, "fail_on_status", uwr->extensions.fail_on_status_str); jk_print_xml_att_string(s, 8, "active", uwr->extensions.active); jk_print_xml_att_string(s, 8, "disabled", uwr->extensions.disabled); @@ -1596,6 +1599,7 @@ static void display_map(jk_ws_service_t jk_printf(s, " source=\"%s\"", uri_worker_map_get_source(uwr, l)); jk_printf(s, " reply_timeout=\"%d\"", uwr->extensions.reply_timeout); jk_printf(s, " sticky_ignore=\"%d\"", uwr->extensions.sticky_ignore); + jk_printf(s, " stateless=\"%d\"", uwr->extensions.stateless); jk_printf(s, " fail_on_status=\"%s\"", uwr->extensions.fail_on_status_str ? uwr->extensions.fail_on_status_str : ""); jk_printf(s, " active=\"%s\"", uwr->extensions.active ? uwr->extensions.active : ""); jk_printf(s, " disabled=\"%s\"", uwr->extensions.disabled ? uwr->extensions.disabled : ""); @@ -1611,6 +1615,7 @@ static void display_map(jk_ws_service_t jk_print_prop_item_string(s, w, worker, "map", count, "source", uri_worker_map_get_source(uwr, l)); jk_print_prop_item_int(s, w, worker, "map", count, "reply_timeout", uwr->extensions.reply_timeout); jk_print_prop_item_int(s, w, worker, "map", count, "sticky_ignore", uwr->extensions.sticky_ignore); + jk_print_prop_item_int(s, w, worker, "map", count, "stateless", uwr->extensions.stateless); jk_print_prop_item_string(s, w, worker, "map", count, "fail_on_status", uwr->extensions.fail_on_status_str); jk_print_prop_item_string(s, w, worker, "map", count, "active", uwr->extensions.active); jk_print_prop_item_string(s, w, worker, "map", count, "disabled", uwr->extensions.disabled); Modified: tomcat/jk/trunk/native/common/jk_uri_worker_map.c URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_uri_worker_map.c?rev=1174449&r1=1174448&r2=1174449&view=diff ============================================================================== --- tomcat/jk/trunk/native/common/jk_uri_worker_map.c (original) +++ tomcat/jk/trunk/native/common/jk_uri_worker_map.c Thu Sep 22 23:23:18 2011 @@ -41,6 +41,7 @@ #define JK_UWMAP_EXTENSION_REPLY_TIMEOUT "reply_timeout=" #define JK_UWMAP_EXTENSION_STICKY_IGNORE "sticky_ignore=" +#define JK_UWMAP_EXTENSION_STATELESS "stateless=" #define JK_UWMAP_EXTENSION_ACTIVE "active=" #define JK_UWMAP_EXTENSION_DISABLED "disabled=" #define JK_UWMAP_EXTENSION_STOPPED "stopped=" @@ -639,6 +640,7 @@ int uri_worker_map_add(jk_uri_worker_map w = jk_pool_strdup(p, worker); uwr->extensions.reply_timeout = -1; uwr->extensions.sticky_ignore = JK_FALSE; + uwr->extensions.stateless = JK_FALSE; uwr->extensions.active = NULL; uwr->extensions.disabled = NULL; uwr->extensions.stopped = NULL; @@ -672,6 +674,15 @@ int uri_worker_map_add(jk_uri_worker_map uwr->extensions.sticky_ignore = JK_FALSE; } } + else if (!strncmp(param, JK_UWMAP_EXTENSION_STATELESS, strlen(JK_UWMAP_EXTENSION_STATELESS))) { + int val = atoi(param + strlen(JK_UWMAP_EXTENSION_STATELESS)); + if (val) { + uwr->extensions.stateless = JK_TRUE; + } + else { + uwr->extensions.stateless = JK_FALSE; + } + } else if (!strncmp(param, JK_UWMAP_EXTENSION_USE_SRV_ERRORS, strlen(JK_UWMAP_EXTENSION_USE_SRV_ERRORS))) { uwr->extensions.use_server_error_pages = atoi(param + strlen(JK_UWMAP_EXTENSION_USE_SRV_ERRORS)); } Modified: tomcat/jk/trunk/native/common/jk_uri_worker_map.h URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_uri_worker_map.h?rev=1174449&r1=1174448&r2=1174449&view=diff ============================================================================== --- tomcat/jk/trunk/native/common/jk_uri_worker_map.h (original) +++ tomcat/jk/trunk/native/common/jk_uri_worker_map.h Thu Sep 22 23:23:18 2011 @@ -75,6 +75,9 @@ struct rule_extension int reply_timeout; /* Whether to ignore session routing info */ int sticky_ignore; + /* Whether the request is stateless and should not + * influence session load balancing */ + int stateless; /* activation state overwrites for load balancers */ /* Number of elements in the array activations. */ int activation_size; Modified: tomcat/jk/trunk/native/common/jk_util.c URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_util.c?rev=1174449&r1=1174448&r2=1174449&view=diff ============================================================================== --- tomcat/jk/trunk/native/common/jk_util.c (original) +++ tomcat/jk/trunk/native/common/jk_util.c Thu Sep 22 23:23:18 2011 @@ -2076,6 +2076,7 @@ void jk_init_ws_service(jk_ws_service_t s->flush_header = JK_FALSE; s->extension.reply_timeout = -1; s->extension.sticky_ignore = JK_FALSE; + s->extension.stateless = JK_FALSE; s->extension.use_server_error_pages = 0; s->extension.activation = NULL; s->extension.fail_on_status_size = 0; Modified: tomcat/jk/trunk/native/iis/jk_isapi_plugin.c URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/iis/jk_isapi_plugin.c?rev=1174449&r1=1174448&r2=1174449&view=diff ============================================================================== --- tomcat/jk/trunk/native/iis/jk_isapi_plugin.c (original) +++ tomcat/jk/trunk/native/iis/jk_isapi_plugin.c Thu Sep 22 23:23:18 2011 @@ -3085,6 +3085,7 @@ static int init_ws_service(isapi_private jk_log(logger, JK_LOG_DEBUG, "Applying service extensions" ); s->extension.reply_timeout = e->reply_timeout; s->extension.sticky_ignore = e->sticky_ignore; + s->extension.stateless = e->stateless; s->extension.use_server_error_pages = e->use_server_error_pages; if (e->activation) { s->extension.activation = jk_pool_alloc(s->pool, e->activation_size * sizeof(int)); Modified: tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml?rev=1174449&r1=1174448&r2=1174449&view=diff ============================================================================== --- tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml (original) +++ tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml Thu Sep 22 23:23:18 2011 @@ -62,6 +62,14 @@ It actually counts the number of requests that do not carry a session id. (rjung) </add> + <add> + URI Map: Add "stateless" extension attributes to uri worker map. + This can improve session load balancing. (rjung) + </add> + <add> + HTTPD: Allow dynamic switching of requests to "stateless" using the + environment variable JK_STATELESS. (rjung) + </add> </changelog> </subsection> </section> Modified: tomcat/jk/trunk/xdocs/reference/apache.xml URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/xdocs/reference/apache.xml?rev=1174449&r1=1174448&r2=1174449&view=diff ============================================================================== --- tomcat/jk/trunk/xdocs/reference/apache.xml (original) +++ tomcat/jk/trunk/xdocs/reference/apache.xml Thu Sep 22 23:23:18 2011 @@ -1124,7 +1124,7 @@ This is available since version 1.2.27. </p> <p> The environment variable -<b>JK_IGNORE_STICKY</b> can be set to disable session stickyness +<b>JK_STICKY_IGNORE</b> can be set to disable session stickyness for individual requests. If the variable is set to an empty string or a nonzero number, session stickyness will be disabled. Setting it to <b>0</b> will reset to the behaviour defined by the worker @@ -1140,6 +1140,19 @@ the application which uses the session. set this environment variable when a user requests a login form to ensure, that this initial session request is balanced non-sticky. </p> +<p> +The environment variable +<b>JK_STATELESS</b> can be used to improve load balancing +for the session based balancing methods <b>Session</b> and +<b>Next</b>. +In this case normally any request which does not come with +a session id counts as a new session. This can be problematic, +if for instance static content is retrieved without a session id. +If you set the environment variable <b>JK_STATELESS</b> for a request, +then the request will not count as a new session, even if it does not +come with a session id. +This is available since version 1.2.33. +</p> </subsection> </section> </body> Modified: tomcat/jk/trunk/xdocs/reference/uriworkermap.xml URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/xdocs/reference/uriworkermap.xml?rev=1174449&r1=1174448&r2=1174449&view=diff ============================================================================== --- tomcat/jk/trunk/xdocs/reference/uriworkermap.xml (original) +++ tomcat/jk/trunk/xdocs/reference/uriworkermap.xml Thu Sep 22 23:23:18 2011 @@ -249,7 +249,8 @@ For a general description of reply timeo <subsection name="Extension sticky_ignore"> <br/> <p> -The extension <code>sticky_ignore</code> can disable session stickyness for a single mapping rule. +The extension <code>sticky_ignore</code> will disable session stickyness for a single +mapping rule. <source> # Disable session stickyness # only for this mapping. @@ -267,6 +268,22 @@ to ensure, that this initial session req This extension is available since version 1.2.33. </p> </subsection> +<subsection name="Extension stateless"> +<br/> +<p> +The extension <code>stateless</code> is only useful when using session based +load balancing. In this case normally any request which does not come with +a session id counts as a new session. If you mark a mapping rule with +the <code>stateless</code> extension, then the requests matching the mapping +rule will not count as a new session, even if they do not come with a session +id. +<source> + # Don't let static content trash our session balancing + /myapp/static/*=myworker;stateless=1 +</source> +This extension is available since version 1.2.33. +</p> +</subsection> <subsection name="Extensions active/disabled/stopped"> <br/> <p> Modified: tomcat/jk/trunk/xdocs/reference/workers.xml URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/xdocs/reference/workers.xml?rev=1174449&r1=1174448&r2=1174449&view=diff ============================================================================== --- tomcat/jk/trunk/xdocs/reference/workers.xml (original) +++ tomcat/jk/trunk/xdocs/reference/workers.xml Thu Sep 22 23:23:18 2011 @@ -544,25 +544,26 @@ working well for most applications. <p> If method is set to <b>S[ession]</b> the balancer will use the number of sessions to find the best worker. Accesses will be distributed according to the -lbfactor in a sliding time window. Because the balancer does not keep any state, +lbfactor in a sliding time window. This method should be used, +if sessions are your limiting resource, e.g. when you only have limited memory +and your sessions need a lot of memory. Because the balancer does not keep any state, it actually does not know the number of sessions. Instead it counts each request without a session cookie or URL encoding as a new session. This method will neither know, when a session is being invalidated, nor will it correct its load numbers -according to session timeouts or worker failover. This method should be used, -if sessions are your limiting resource, e.g. when you only have limited memory -and your sessions need a lot of memory. +according to session timeouts or worker failover. If you know request URLs, that will be +called without a session ID but should not be counted as new sessions, you should +add them to the <b>stateless</b> mapping rule extension or set the Apache HTTPD +environment variable <b>JK_STATELESS</b> for them. </p> <p> If method is set to <b>N[ext]</b> the balancer will again use the number of sessions -to find the best worker. The difference to the <b>S[ession]</b> method is how -the session count is handled in the sliding time window. The <b>N[ext]</b> method -does not divide by 2, instead it subtracts the minimum number. This should effectively -result in a round-robin session balancing, thus the name <b>N[ext]</b>. -Under high load, the two session balancing -methods will result in a similar distribution, but <b>N[ext]</b> will be better -if you need to distribute small numbers of sessions. Again this method will -neither know, when a session is being invalidated, nor will it correct its load numbers -according to session timeouts or worker failover. +to find the best worker. All remarks concerning the <b>Session</b>method apply as well. +The difference to the <b>Session</b> method is how the session count is handled in the +sliding time window. The <b>Next</b> method does not divide by 2, instead it subtracts +the current minimum number. This should effectively result in a round-robin session +balancing, thus the name <b>Next</b>. Under high load, the two session balancing +methods will result in a similar distribution, but <b>Next</b> will be better +if you need to distribute small numbers of sessions. </p> <p> If set to <b>T[raffic]</b> the balancer will use @@ -580,8 +581,9 @@ interesting, if your request take a long application. </p> <p> -This feature has been added in <b>jk 1.2.9</b>. -The Session method has been added in <b>jk 1.2.20</b>. +This feature has been added in version <b>1.2.9</b>. +The Session method has been added in version <b>1.2.20</b>, +the <b>Next</b> method in version <b>1.2.32</b>.. </p> </directive> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org