tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Rainer Jung" <tomcat-...@kippdata.de>
Subject Re: Question about new mod_jk jk_lb_worker.c
Date Sun, 14 Nov 2004 15:31:10 GMT
Hi Mladen,

0) Any ideas on rotating the mod_jk log file?

>> 4) Open Problem

> This should work now with the latest patches.

Excellent! Actually I tried to understand the new principles. Using an old
style paper computer I can see that the values for lb_value are periodic.
But I must confirm, that I did not mathematically understand the
algorithm, maybe due to being a little ill. Are the mathematically
foundations behind that simple algorithm described anywhere?

>> 1) Limiting new application sessions if load is to high.
>>
>
> There is a problem with that. I made a implementation counting the
> number of busy childs/threads from scoreboard (took me entire day),
> but again we should count the number of connections to tomcat, cause
> the apache might be serving static content.
> Anyhow the idea is great and I'll implement it in the new mod_proxy
> for Apache 2.2 where we have extra slots in the scoreboard.
> Sad but we can not do that inside mod_jk unless we implement our
> own shared memory, that was prover to be bogus in jk2.

Apache serving static content is not a problem according to our
experience. Static content usually serves in very well under a second
(depending mostly on internet speed). The idea here is to detect a problem
with the application getting slow, e.g. because of backend systems not
responding fast enough. In this situation we want to limit creation of new
sessions. Counting the static requests doesn't really matter for us.

Example: During normal operation there are 5 static requests in work and
10 dynamic ones (that take much longer to complete). When there is a
problem with backend systems we will have 15 static ones, but more than
100 dynamic ones. So either counting or ommiting the static ones seems to
make no big difference.

You might want to take a look at the attached patch "patch_overload.txt"
for jk/native/apache1.3/mod_jk.c version 1.52. I don't have a patch for
Apache 2. The Patch places every change inside "#ifdef OVERLOAD". Also
there are some DEBUG-Log-Statements put inside "#ifdef DEBUG" which I
assume can now be done more consistently with your TRACE features.

Of course the "best" observable value would be the number of requests
belonging to the same webapp. So some possible enhancement would be to
count only requests with a fix URL prefix (that's not contained in the
patch).

>> 2) Multi-Cluster-Routing
>>
>
> Can you write some use case for that and perhaps some simple algo
> too. What about sticky-sessions and forcing failower if we do not have
> session replication?

Use case:

Enterprise application with redundant internet connections A and B.
A consists of two Apache instances A.a1 und A.a2, B of B.a1 and B.a2.
Behind are 4 Tomcat A.t1, A.t2, B.t1, B.t2.

A.t1 and A.t2 are clustered, B.t1 and B.t2 are clustered. mod_jk uses load
balancing with sticky sessions.

All Apaches can connect to any Tomcat, but A.t1 is local for A.a1, A.t2
for A.a2, B.t1 for B.a1 and B.t2 for B.a2:

A.a1   A.a2   B.a1   B.a2
 ||  X  ||  X  ||  X  ||
A.t1---A.t2   B.t1---B.t2

A.t1 and A.t2 are put into the same "domain" "A" in workers.properties,
B.t1 and B.t2 are put into the same "domain" "B" in workers.properties.

Now if you shutdown e.g. tomcat B.t1 for service/update (or if it breaks)
All apaches will know from the domain configuration, that sticky requests
for B.t1 have to go to B.t2. This is important, since only on that tomcat
the replicated sessions from B.t1 will exist.

Without domains you have to put all the Tomcats in one cluster. But then
all sessions are replicated to all tomcats. We have a production side
using 3x3=9 tomcats and a cluster with 9 nodes would mean too much
overhead.

The implementation uses and additional worker attribute domain, and if a
session has a jvmRoute, is sticky and the correct worker is in error state
another worker with the same domain attribute is chosen.

I have an implementation, but I have to adapt to your code changes. The
patch will only concern common/jk_util.c for configuration and
common/jk_lb_worker.c. I could provide the code, if you are interested.

For applications using sessions but without session replication I don't
see a way how to successfully fail over. Maybe I don't understand that
part of your question?

>> 3) Idle connection disconnect
> Use worker mpm. We just can not make maintainer thread for
> non-treaded mpm's like apache1.2 or prefork.

I don't use a seperate thread. I implemented this feature for Apache 1.3.
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 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;
}

Thank's for the discussion!!

Rainer



---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org


Mime
View raw message