Rather ugly, but in the http module rather than mpm. Still needs some work but
works in most cases here. I think there are instances where an aborted
connection will not decrement the count, maybe. Had to add configuration stuff
to http_core, since it, wrongly in my opinion, uses the core server config
structures.
Patch is against 2.2.3, since that's what we run mostly around here.
--
Brian Akins
Chief Operations Engineer
Turner Digital Media Technologies
diff -ur httpd-2.2.3/include/http_core.h
httpd-2.2.3-keepalive/include/http_core.h
--- httpd-2.2.3/include/http_core.h 2006-07-11 23:38:44.000000000 -0400
+++ httpd-2.2.3-keepalive/include/http_core.h 2006-11-15 15:26:14.000000000
-0500
@@ -682,6 +682,8 @@
/* ---------------------------------------------------------------------- */
+AP_DECLARE(int) ap_can_keepalive(request_rec *r);
+
#ifdef __cplusplus
}
#endif
diff -ur httpd-2.2.3/modules/http/http_core.c
httpd-2.2.3-keepalive/modules/http/http_core.c
--- httpd-2.2.3/modules/http/http_core.c 2006-07-24 09:34:19.000000000
-0400
+++ httpd-2.2.3-keepalive/modules/http/http_core.c 2006-11-15
17:20:25.000000000 -0500
@@ -35,6 +35,8 @@
#include "mod_core.h"
+module AP_MODULE_DECLARE_DATA http_module;
+
/* Handles for core filters */
AP_DECLARE_DATA ap_filter_rec_t *ap_http_input_filter_handle;
AP_DECLARE_DATA ap_filter_rec_t *ap_http_header_filter_handle;
@@ -42,6 +44,28 @@
AP_DECLARE_DATA ap_filter_rec_t *ap_http_outerror_filter_handle;
AP_DECLARE_DATA ap_filter_rec_t *ap_byterange_filter_handle;
+
+typedef struct {
+ int maxkaconn;
+} http_core_conf_t;
+
+static apr_uint32_t current_ka = 0;
+
+static void *create_http_conf(apr_pool_t * p, server_rec *s)
+{
+ http_core_conf_t *conf = apr_pcalloc(p, sizeof(http_core_conf_t));
+ return conf;
+}
+
+static const char *set_maxkaconn(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ http_core_conf_t *conf
+ = ap_get_module_config(cmd->server->module_config, &http_module);
+ conf->maxkaconn = atoi(arg);
+ return NULL;
+}
+
static const char *set_keep_alive_timeout(cmd_parms *cmd, void *dummy,
const char *arg)
{
@@ -94,6 +118,9 @@
"or 0 for infinite"),
AP_INIT_TAKE1("KeepAlive", set_keep_alive, NULL, RSRC_CONF,
"Whether persistent connections should be On or Off"),
+ AP_INIT_TAKE1("MaxKeepAliveConnections", set_maxkaconn, NULL, GLOBAL_ONLY,
+ "Maximum number of Keep-Alive connections per child, "
+ "or 0 for infinite"),
{ NULL }
};
@@ -206,9 +233,43 @@
return OK;
}
+AP_DECLARE(int) ap_can_keepalive(request_rec *r) {
+ http_core_conf_t *conf
+ = ap_get_module_config(r->server->module_config, &http_module);
+ apr_uint32_t current;
+
+ if(conf->maxkaconn) {
+ current = apr_atomic_read32(¤t_ka);
+
+ if(current >= conf->maxkaconn) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static apr_status_t keepalive_cleanup(void *data)
+{
+ conn_rec *c = (conn_rec *)data;
+
+ /*need to check for abort?? Also, what happens when client closes and we
are in keepalive?
+ * should we register a cleanup on connection pool?
+ */
+ if(c->keepalive == AP_CONN_KEEPALIVE) {
+ apr_atomic_inc32(¤t_ka);
+ }
+
+ return APR_SUCCESS;
+}
+
static int http_create_request(request_rec *r)
{
if (!r->main && !r->prev) {
+ conn_rec *c = r->connection;
+ http_core_conf_t *conf
+ = ap_get_module_config(r->server->module_config, &http_module);
+
ap_add_output_filter_handle(ap_byterange_filter_handle,
NULL, r, r->connection);
ap_add_output_filter_handle(ap_content_length_filter_handle,
@@ -217,6 +278,15 @@
NULL, r, r->connection);
ap_add_output_filter_handle(ap_http_outerror_filter_handle,
NULL, r, r->connection);
+
+ if(conf->maxkaconn) {
+ /*this connection had been kept alive, but it's now "active"
again*/
+ if(c->keepalive == AP_CONN_KEEPALIVE) {
+ apr_atomic_dec32(¤t_ka);
+ }
+ apr_pool_cleanup_register(r->pool, c, keepalive_cleanup,
+ keepalive_cleanup);
+ }
}
return OK;
@@ -265,7 +335,7 @@
STANDARD20_MODULE_STUFF,
NULL, /* create per-directory config structure */
NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
+ create_http_conf, /* create per-server config structure */
NULL, /* merge per-server config structures */
http_cmds, /* command apr_table_t */
register_hooks /* register hooks */
diff -ur httpd-2.2.3/modules/http/http_protocol.c
httpd-2.2.3-keepalive/modules/http/http_protocol.c
--- httpd-2.2.3/modules/http/http_protocol.c 2006-07-11 23:38:44.000000000
-0400
+++ httpd-2.2.3-keepalive/modules/http/http_protocol.c 2006-11-15
15:21:18.000000000 -0500
@@ -157,6 +157,15 @@
*/
#define METHOD_NUMBER_LAST 62
+static int can_it_keepalive(request_rec *r) {
+ if(!ap_can_keepalive(r)) {
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "Maximum keepalive connections reached");
+ return 0;
+ } else {
+ return 1;
+ }
+}
AP_DECLARE(int) ap_set_keepalive(request_rec *r)
{
@@ -212,9 +221,9 @@
&& (!apr_table_get(r->subprocess_env, "nokeepalive")
|| apr_table_get(r->headers_in, "Via"))
&& ((ka_sent = ap_find_token(r->pool, conn, "keep-alive"))
- || (r->proto_num >= HTTP_VERSION(1,1)))) {
+ || (r->proto_num >= HTTP_VERSION(1,1))) && can_it_keepalive(r)) {
int left = r->server->keep_alive_max - r->connection->keepalives;
-
+
r->connection->keepalive = AP_CONN_KEEPALIVE;
r->connection->keepalives++;