DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG·
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=32319>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND·
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=32319

           Summary: Idle connection disconnect - free waiting tomcat threads
           Product: Tomcat 5
           Version: 5.0.30
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Native:JK
        AssignedTo: [EMAIL PROTECTED]
        ReportedBy: [EMAIL PROTECTED]


Idle connection disconnect - free waiting tomcat threads

A mod_jk connection consumes one tomcat connector thread, even if it's idle for
a long time. The idle connection check in mod_jk only works, if the idle
connection is going to be used. Then it is checked if it was idle for too long
and probably is beeing closed and reconnected.

I implemented a feature, where in configurable intervals all workers of an lb
worker are checked for idle connections, even the ones which are not returned by
get_most_suitable_worker. It is only necessary, that the apache process uses
some worker inside the same lb. This way connections only used temporarily (e.g.
due to restart of clustered nodes) will be reliably closed after some idle 
time. 

My implementation currently is only for Apache 1.3 and works very well under
Solaris. I don't know, if it will work under Win/Netware/etc.. It does not use a
seperate maintenance thread. The principles are the following (and I can sent
complete code if you are interested):

a) In common/service.h in jk_worker define an additional hook JK_METHOD check
to be implemented by the workers:

    /*
     * Check all workers on a regular basis,
     * even if they do not process requests.
     */
    int (JK_METHOD *check)(jk_worker_t *w,
                           int force,
                           jk_logger_t *l);

b) In common/jk_worker.c provide an entry point wc_check, that will call
the check method for all workers in the worker_map:

void wc_check(jk_logger_t *l)
{
    int sz = map_size(worker_map);
    jk_log(l, JK_LOG_DEBUG, "wc_check got %d workers to check\n", sz);
    if(sz > 0) {
        int i;
        for(i = 0 ; i < sz ; i++) {
            jk_worker_t *w = map_value_at(worker_map, i);
            if(w) {
                w->check(w, 0, l);
            }
        }
    }
}

c) In apache/1.3/mod_jk.c in method jk_handler before calling
wc_get_worker_for_name call wc_check:

        wc_check(l);

d) For the individual worker types implement the check method according to
your needs. For instance for the ajp13 worker I did:

/* Check uses the same function for ajp13 and ajp14 */
static int JK_METHOD check(jk_worker_t *pThis,
                           int force,
                           jk_logger_t *l)
{
    return (ajp_check(pThis, force, l));
}
int JK_METHOD ajp13_worker_factory(
...
    aw->check_interval         = AJP_DEF_CHECK_INTERVAL;
    aw->last_check             = time(NULL);
...
    aw->worker.check           = check;

using a generalized ajp_check from common/jk_ajp_common.c:

/*
* Check all workers on a regular basis,
* even if they do not process requests.
* Currently only one function is implemented:
* close endpoint sockets if endpoint has been idle for too long.
*/
int ajp_check(jk_worker_t *pThis,
              int force,
              jk_logger_t *l)
{
    jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::check\n");

    if (pThis && pThis->worker_private) {
        ajp_worker_t *p = pThis->worker_private;
        if (force || p->check_interval) {
            time_t now;
            unsigned elapsed = 0;
            now = time(NULL);
            if (! force) {
                elapsed = (unsigned)(now-p->last_check);
            }
            if (force || ( elapsed > p->check_interval )) {
                p->last_check = now;
                /* Handle endpoint idle timeouts */
                close_idle_endpoints(p, l);
            }
        }
        return JK_TRUE;
    }
    jk_log(l, JK_LOG_ERROR,
           "In jk_worker_t::check, NULL parameters\n");
    return JK_FALSE;
}

e) Similarly for an lb worker I use

static int JK_METHOD check(jk_worker_t *pThis,
                           int force,
                           jk_logger_t *l)
{
    jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::check\n");

    if(pThis && pThis->worker_private) {
        lb_worker_t *p = pThis->worker_private;
        if (force || p->check_interval) {
            time_t now;
            unsigned elapsed = 0;
            now = time(NULL);
            if (! force) {
                elapsed = (unsigned)(now-p->last_check);
            }
            if (force || ( elapsed > p->check_interval )) {
                int i;
                p->last_check = now;
                for(i = 0 ; i < p->num_of_workers ; i++) {
                    /* Calling check for balanced workers using force flag */
                    p->lb_workers[i].w->check(p->lb_workers[i].w, 1, l);
                }
            }
        }
        return JK_TRUE;
    }
    jk_log(l, JK_LOG_ERROR,
           "In jk_worker_t::check, NULL parameters\n");
    return JK_FALSE;
}

-- 
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to