You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Jan Singer <ja...@singer-tc.de> on 2002/06/19 15:58:12 UTC

[PATCH] AJP13 setting socket timeout / keepalive

Hi,

we are using AJP13 through firewall which kills idle connections. This
causes mod_jk to never give a reponse to some requests (see my earlier
message for details). So I wrote a patch that adds two different ways to
overcome this behaviour:

1. Setting SO_KEEPALIVE on sockets

By adding the option "worker.<name>.socket_keepalive = 1" to
workers.properties, the option SO_KEEPALIVE is set on all sockets for
this worker. If one configures the keepalive_interval to a proper time,
the connection won't be idle long enough to get killed by the firewall.

2. Setting a timout for sockets

One can now set a timeout for open sockets in the workers.properties
with "worker.<name>.socket_timeout = <time_in_seconds>". When choosing
an endpoint for a request and the assigned socket is open, it will be
closed if it was not used for the configured time.

We choose the second method setting the timeout to 50 minutes and it
works for us. Maybe this could help others with similar configurations. 

The default behaviour isn't changed from the unpatched version.

Would someone please review?

Jan

Index: jakarta-tomcat-connectors/jk/native/common/jk_ajp12_worker.c
===================================================================
RCS file:
/home/cvspublic/jakarta-tomcat-connectors/jk/native/common/jk_ajp12_work
er.c,v
retrieving revision 1.6
diff -b -u -r1.6 jk_ajp12_worker.c
--- jakarta-tomcat-connectors/jk/native/common/jk_ajp12_worker.c
4 Dec 2001 19:39:54 -0000	1.6
+++ jakarta-tomcat-connectors/jk/native/common/jk_ajp12_worker.c
19 Jun 2002 12:48:37 -0000
@@ -131,6 +131,7 @@
         for(attempt = 0 ; attempt < p->worker->connect_retry_attempts ;
attempt++) {
             p->sd = jk_open_socket(&p->worker->worker_inet_addr, 
                                    JK_TRUE, 
+                                   JK_FALSE,
                                    l);
 
             jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::service, sd =
%d\n", p->sd);
Index: jakarta-tomcat-connectors/jk/native/common/jk_ajp13.h
===================================================================
RCS file:
/home/cvspublic/jakarta-tomcat-connectors/jk/native/common/jk_ajp13.h,v
retrieving revision 1.8
diff -b -u -r1.8 jk_ajp13.h
--- jakarta-tomcat-connectors/jk/native/common/jk_ajp13.h	4 Dec
2001 19:48:41 -0000	1.8
+++ jakarta-tomcat-connectors/jk/native/common/jk_ajp13.h	19 Jun
2002 12:48:37 -0000
@@ -81,6 +81,7 @@
 #define JK_FATAL_ERROR              (-3)
 #define JK_CLIENT_ERROR             (-4)
 #define AJP13_MAX_SEND_BODY_SZ      (DEF_BUFFER_SZ - 6)
+#define AJP13_DEF_TIMEOUT           (0) /* Idle timout for pooled
connections */
 
 /*
  * Message does not have a response (for example,
JK_AJP13_END_RESPONSE)
Index: jakarta-tomcat-connectors/jk/native/common/jk_ajp_common.c
===================================================================
RCS file:
/home/cvspublic/jakarta-tomcat-connectors/jk/native/common/jk_ajp_common
.c,v
retrieving revision 1.25
diff -b -u -r1.25 jk_ajp_common.c
--- jakarta-tomcat-connectors/jk/native/common/jk_ajp_common.c	10 May
2002 23:58:40 -0000	1.25
+++ jakarta-tomcat-connectors/jk/native/common/jk_ajp_common.c	19 Jun
2002 12:48:38 -0000
@@ -584,9 +584,11 @@
     unsigned attempt;
 
     for(attempt = 0 ; attempt < ae->worker->connect_retry_attempts ;
attempt++) {
-        ae->sd = jk_open_socket(&ae->worker->worker_inet_addr, JK_TRUE,
l);
+        ae->sd = jk_open_socket(&ae->worker->worker_inet_addr, JK_TRUE,
ae->worker->keepalive, l);
         if(ae->sd >= 0) {
             jk_log(l, JK_LOG_DEBUG, "In
jk_endpoint_t::ajp_connect_to_endpoint, connected sd = %d\n", ae->sd);
+            /* set last_access */
+            ae->last_access = time(NULL);
 
 			/* Check if we must execute a logon after the
physical connect */
 			if (ae->worker->logon != NULL)
@@ -1232,13 +1234,19 @@
         cache = AJP13_DEF_CACHE_SZ;
     }
     else {
-        jk_log(l, JK_LOG_DEBUG, "In jk_worker_t::validate unknown
protocol %d\n", proto);
+        jk_log(l, JK_LOG_DEBUG, "In jk_worker_t::init, unknown protocol
%d\n", proto);
         return JK_FALSE;
     }
 
     if (pThis && pThis->worker_private) {
         ajp_worker_t *p = pThis->worker_private;
         int cache_sz = jk_get_worker_cache_size(props, p->name, cache);
+        int socket_timeout = jk_get_worker_socket_timeout(props,
p->name, AJP13_DEF_TIMEOUT);
+        int socket_keepalive = jk_get_worker_socket_keepalive(props,
p->name, JK_FALSE);
+
+        jk_log(l, JK_LOG_DEBUG, "In jk_worker_t::init, setting socket
timeout to %d\n", socket_timeout);
+        p->socket_timeout = socket_timeout;
+        p->keepalive = socket_keepalive;
         
         /* 
          *  Need to initialize secret here since we could return from
inside
@@ -1373,6 +1381,18 @@
                 }
                 JK_LEAVE_CS(&aw->cs, rc);
                 if (ae) {
+                  if (ae->sd > 0) {
+                    /* Handle timeouts for open sockets */
+                    time_t now = time(NULL);
+                    int elapsed = abs(difftime(now, ae->last_access));
+                    ae->last_access = now;
+                    jk_log(l, JK_LOG_DEBUG, "In
jk_endpoint_t::ajp_get_endpoint, time elapsed since last request = %d
seconds\n", elapsed);
+                    if (aw->socket_timeout > 0 && elapsed >
aw->socket_timeout) {
+                      jk_close_socket(ae->sd);
+                      jk_log(l, JK_LOG_DEBUG, "In
jk_endpoint_t::ajp_get_endpoint, reached socket timeout, closed sd =
%d\n", ae->sd);
+                      ae->sd = -1; /* just to avoid twice close */
+                    }
+                  }
                     *je = &ae->endpoint;
                     return JK_TRUE;
                 }
@@ -1383,6 +1403,7 @@
         if (ae) {
             ae->sd = -1;
             ae->reuse = JK_FALSE;
+            ae->last_access = time(NULL);
             jk_open_pool(&ae->pool, ae->buf, sizeof(ae->buf));
             ae->worker = pThis->worker_private;
             ae->endpoint.endpoint_private = ae;
Index: jakarta-tomcat-connectors/jk/native/common/jk_ajp_common.h
===================================================================
RCS file:
/home/cvspublic/jakarta-tomcat-connectors/jk/native/common/jk_ajp_common
.h,v
retrieving revision 1.14
diff -b -u -r1.14 jk_ajp_common.h
--- jakarta-tomcat-connectors/jk/native/common/jk_ajp_common.h	6 Feb
2002 19:11:23 -0000	1.14
+++ jakarta-tomcat-connectors/jk/native/common/jk_ajp_common.h	19 Jun
2002 12:48:38 -0000
@@ -269,6 +269,13 @@
      */ 
     int (* logon)(ajp_endpoint_t *ae,
                   jk_logger_t    *l);
+
+    /*
+    * Handle Socket Timeouts
+    */
+    unsigned socket_timeout;
+    unsigned keepalive;
+
 }; 
  
 
@@ -288,6 +295,11 @@
     jk_endpoint_t endpoint;
 
     unsigned left_bytes_to_send;
+
+    /* time of the last request
+       handled by this endpoint */
+    time_t last_access;
+
 };
 
 /*
Index: jakarta-tomcat-connectors/jk/native/common/jk_connect.c
===================================================================
RCS file:
/home/cvspublic/jakarta-tomcat-connectors/jk/native/common/jk_connect.c,
v
retrieving revision 1.3
diff -b -u -r1.3 jk_connect.c
--- jakarta-tomcat-connectors/jk/native/common/jk_connect.c	4 Jul
2001 16:59:38 -0000	1.3
+++ jakarta-tomcat-connectors/jk/native/common/jk_connect.c	19 Jun
2002 12:48:39 -0000
@@ -109,6 +109,7 @@
 
 int jk_open_socket(struct sockaddr_in *addr, 
                    int ndelay,
+                   int keepalive,
                    jk_logger_t *l)
 {
     int sock;
@@ -134,6 +135,7 @@
 
         /* Check if we connected */
         if(0 == ret) {
+                                                int keep = 1;
             if(ndelay) {
                 int set = 1;
 
@@ -144,6 +146,15 @@
                            (char *)&set, 
                            sizeof(set));
             }   
+
+                                                if (keepalive) {
+                                                        jk_log(l,
JK_LOG_DEBUG, "jk_open_socket, set SO_KEEPALIVE to on\n");
+
setsockopt(sock,
+
SOL_SOCKET,
+
SO_KEEPALIVE,
+
(char *)&keep,
+
sizeof(keep));
+                                          }
 
             jk_log(l, JK_LOG_DEBUG, "jk_open_socket, return, sd =
%d\n", sock);
             return sock;
Index: jakarta-tomcat-connectors/jk/native/common/jk_connect.h
===================================================================
RCS file:
/home/cvspublic/jakarta-tomcat-connectors/jk/native/common/jk_connect.h,
v
retrieving revision 1.2
diff -b -u -r1.2 jk_connect.h
--- jakarta-tomcat-connectors/jk/native/common/jk_connect.h	18 Jun
2001 14:15:36 -0000	1.2
+++ jakarta-tomcat-connectors/jk/native/common/jk_connect.h	19 Jun
2002 12:48:39 -0000
@@ -81,6 +81,7 @@
 
 int jk_open_socket(struct sockaddr_in *addr, 
                    int ndelay,
+                   int keepalive,
                    jk_logger_t *l);
 
 int jk_close_socket(int s);
Index: jakarta-tomcat-connectors/jk/native/common/jk_util.c
===================================================================
RCS file:
/home/cvspublic/jakarta-tomcat-connectors/jk/native/common/jk_util.c,v
retrieving revision 1.14
diff -b -u -r1.14 jk_util.c
--- jakarta-tomcat-connectors/jk/native/common/jk_util.c	15 May
2002 21:00:29 -0000	1.14
+++ jakarta-tomcat-connectors/jk/native/common/jk_util.c	19 Jun
2002 12:48:39 -0000
@@ -83,6 +83,8 @@
 #define PORT_OF_WORKER              ("port")
 #define TYPE_OF_WORKER              ("type")
 #define CACHE_OF_WORKER             ("cachesize")
+#define SOCKET_TIMEOUT_OF_WORKER    ("socket_timeout")
+#define SOCKET_KEEPALIVE_OF_WORKER  ("socket_keepalive")
 #define LOAD_FACTOR_OF_WORKER       ("lbfactor")
 #define BALANCED_WORKERS            ("balanced_workers")
 #define LOCAL_WORKER_ONLY_FLAG      ("local_worker_only")
@@ -392,6 +394,36 @@
     }
 
     sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, CACHE_OF_WORKER);
+
+    return map_get_int(m, buf, def);
+}
+
+int jk_get_worker_socket_timeout(jk_map_t *m,
+                             const char *wname,
+                             int def)
+{
+    char buf[1024];
+
+    if(!m || !wname) {
+        return -1;
+    }
+
+    sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname,
SOCKET_TIMEOUT_OF_WORKER);
+
+    return map_get_int(m, buf, def);
+}
+
+int jk_get_worker_socket_keepalive(jk_map_t *m,
+                             const char *wname,
+                             int def)
+{
+    char buf[1024];
+
+    if(!m || !wname) {
+        return -1;
+    }
+
+    sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname,
SOCKET_KEEPALIVE_OF_WORKER);
 
     return map_get_int(m, buf, def);
 }
Index: jakarta-tomcat-connectors/jk/native/common/jk_util.h
===================================================================
RCS file:
/home/cvspublic/jakarta-tomcat-connectors/jk/native/common/jk_util.h,v
retrieving revision 1.6
diff -b -u -r1.6 jk_util.h
--- jakarta-tomcat-connectors/jk/native/common/jk_util.h	15 May
2002 21:00:29 -0000	1.6
+++ jakarta-tomcat-connectors/jk/native/common/jk_util.h	19 Jun
2002 12:48:39 -0000
@@ -110,6 +110,14 @@
                              const char *wname,
                              int def);
 
+int jk_get_worker_socket_timeout(jk_map_t *m,
+                             const char *wname,
+                             int def);
+
+int jk_get_worker_socket_keepalive(jk_map_t *m,
+                             const char *wname,
+                             int def);
+
 char * jk_get_worker_secret_key(jk_map_t *m,
                                 const char *wname);
 

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>