httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Bill Stoddard" <b...@wstoddard.com>
Subject Re: [PATCH-concept] more dynamic configuration
Date Fri, 06 Jul 2001 19:59:42 GMT
-1 in concept.

The server is not architected to handle dynamically changing runtime parameters.  I have
worked on network servers with dynamic runtime configuration (more than one) and it is a
support nightmare. This will add a lot of complexity and non intuitive bahaviour to the
server for relatively little benefit. If lots of Apache users come out in support for
function like this, I'll reconsider.

Bill

>
> Attached is a patch that adds more dynamic configuration.
> It places some of the MPM variables such as 'ap_max_daemons_limit',
> 'ap_daemons_limit', 'ap_daemons_min_free' and 'ap_daemons_max_free'
> in the scoreboard. This enables management modules to do
> dynamic (runtime) configuration without requiring a restart of the
> Apache HTTP server.
>
>
> How is it done:
> 1) The patch adds a hook after the creation of the scoreboard
> which is used by the MPM to transfer the variables in
> the scoreboard and allows a management modules to change
> those.
> 2) The MPM during its server maintenance (or spawning of extra
> processes)
> use the variables that are now in the scoreboard.
> The children are not influenced in performance from this
> for the variables: 'ap_max_daemons_limit',
> 'ap_daemons_limit', 'ap_daemons_min_free' and 'ap_daemons_max_free'.
> 3) The a child uses now the 'max_requests_per_child' from the
> scoreboard.
> Which is has little or no impact on the request processing.
>
> This patch works only for the PREFORK MPM. If it is seen as usefull,
> we can do the same with the other MPMs and, for instance, add
> 'ap_threads_min_spare' in the scoreboard as well to allow dynamic
> configuration.
>
> Let me know what you think of it.
>
> Harrie
> --
> address: Covalent Technologies, 645 Howard St, San Francisco, CA - 94105
> phone: +1-415-536-5221                               fax:+1-415-536-5210
> personal website: http://www.lisanza.net/


--------------------------------------------------------------------------------


> diff -ru ../httpd-2.0/include/ap_mpm.h ./include/ap_mpm.h
> --- ../httpd-2.0/include/ap_mpm.h Wed Jun 27 10:43:28 2001
> +++ ./include/ap_mpm.h Tue Jul  3 14:18:43 2001
> @@ -169,6 +169,7 @@
>  #define AP_MPMQ_MAX_SPARE_DAEMONS     9  /* Max # of spare daemons       */
>  #define AP_MPMQ_MAX_SPARE_THREADS    10  /* Max # of spare threads       */
>  #define AP_MPMQ_MAX_REQUESTS_DEAMON  11  /* Max # of requests per daemon */
> +#define AP_MPMQ_DAEMONS_USED         12  /* Used # of scoreboard slots   */
>
>
>  /**
> diff -ru ../httpd-2.0/include/scoreboard.h ./include/scoreboard.h
> --- ../httpd-2.0/include/scoreboard.h Sat Jun  9 17:37:59 2001
> +++ ./include/scoreboard.h Thu Jul  5 09:09:19 2001
> @@ -73,6 +73,8 @@
>  #include "apr_thread_proc.h"
>  #include "apr_portable.h"
>
> +AP_DECLARE_HOOK(void,setup_shared_info,(apr_pool_t *pconf,apr_pool_t *plog,server_rec
*s));
> +
>  /* Scoreboard info on a process is, for now, kept very brief ---
>   * just status value and pid (the latter so that the caretaker process
>   * can properly update the scoreboard when a process dies).  We may want
> @@ -169,6 +171,11 @@
>      ap_scoreboard_e sb_type;
>      ap_generation_t running_generation; /* the generation of children which
>                                           * should still be serving requests. */
> +    int ap_max_daemons_limit;           /* used # of scoreboard slots        */
> +    int ap_daemons_limit;               /* max # of clients                  */
> +    int ap_daemons_max_free;            /* max # of spare servers            */
> +    int ap_daemons_min_free;            /* min # of spare servers            */
> +    int ap_max_requests_per_child;      /* max # of requests per child       */
>  } global_score;
>
>  /* stuff which the parent generally writes and the children rarely read */
> diff -ru ../httpd-2.0/server/mpm/prefork/mpm.h ./server/mpm/prefork/mpm.h
> --- ../httpd-2.0/server/mpm/prefork/mpm.h Wed Jun  6 17:09:16 2001
> +++ ./server/mpm/prefork/mpm.h Tue Jul  3 13:56:27 2001
> @@ -75,7 +75,6 @@
>  #define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
>
>  extern int ap_threads_per_child;
> -extern int ap_max_daemons_limit;
>  extern server_rec *ap_server_conf;
>  extern char ap_coredump_dir[MAX_STRING_LEN];
>  #endif /* APACHE_MPM_PREFORK_H */
> diff -ru ../httpd-2.0/server/mpm/prefork/prefork.c ./server/mpm/prefork/prefork.c
> --- ../httpd-2.0/server/mpm/prefork/prefork.c Wed Jun 27 10:43:39 2001
> +++ ./server/mpm/prefork/prefork.c Thu Jul  5 11:37:25 2001
> @@ -151,7 +151,6 @@
>   * to deal with MaxClients changes across SIGWINCH restarts.  We use this
>   * value to optimize routines that have to scan the entire scoreboard.
>   */
> -int ap_max_daemons_limit = -1;
>  server_rec *ap_server_conf;
>
>  char ap_coredump_dir[MAX_STRING_LEN];
> @@ -316,7 +315,10 @@
>  {
>      switch(query_code){
>          case AP_MPMQ_MAX_DAEMONS:
> -            *result = ap_daemons_limit;
> +            *result = ap_scoreboard_image->global.ap_daemons_limit;
> +            return APR_SUCCESS;
> +        case AP_MPMQ_DAEMONS_USED:
> +            *result = ap_scoreboard_image->global.ap_max_daemons_limit;
>              return APR_SUCCESS;
>          case AP_MPMQ_IS_THREADED:
>              *result = AP_MPMQ_NOT_SUPPORTED;
> @@ -334,19 +336,19 @@
>              *result = 0;
>              return APR_SUCCESS;
>          case AP_MPMQ_MIN_SPARE_DEAMONS:
> -            *result = ap_daemons_min_free;
> +            *result = ap_scoreboard_image->global.ap_daemons_min_free;
>              return APR_SUCCESS;
>          case AP_MPMQ_MIN_SPARE_THREADS:
>              *result = 0;
>              return APR_SUCCESS;
>          case AP_MPMQ_MAX_SPARE_DAEMONS:
> -            *result = ap_daemons_max_free;
> +            *result = ap_scoreboard_image->global.ap_daemons_max_free;
>              return APR_SUCCESS;
>          case AP_MPMQ_MAX_SPARE_THREADS:
>              *result = 0;
>              return APR_SUCCESS;
>          case AP_MPMQ_MAX_REQUESTS_DEAMON:
> -            *result = ap_max_requests_per_child;
> +            *result = ap_scoreboard_image->global.ap_max_requests_per_child;
>              return APR_SUCCESS;
>      }
>      return APR_ENOTIMPL;
> @@ -361,7 +363,7 @@
>  {
>      int n, pid;
>
> -    for (n = 0; n < ap_max_daemons_limit; ++n) {
> +    for (n = 0; n < ap_scoreboard_image->global.ap_max_daemons_limit; ++n) {
>          ap_sync_scoreboard_image();
>   if (ap_scoreboard_image->servers[n][0].status != SERVER_DEAD &&
>   kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) {
> @@ -598,8 +600,8 @@
>
>   apr_pool_clear(ptrans);
>
> - if ((ap_max_requests_per_child > 0
> -      && requests_this_child++ >= ap_max_requests_per_child)) {
> + if ((ap_scoreboard_image->global.ap_max_requests_per_child > 0
> +      && requests_this_child++ >=
ap_scoreboard_image->global.ap_max_requests_per_child)) {
>       clean_child_exit(0);
>   }
>
> @@ -836,8 +838,8 @@
>  {
>      int pid;
>
> -    if (slot + 1 > ap_max_daemons_limit) {
> - ap_max_daemons_limit = slot + 1;
> +    if (slot + 1 > ap_scoreboard_image->global.ap_max_daemons_limit) {
> + ap_scoreboard_image->global.ap_max_daemons_limit = slot + 1;
>      }
>
>      if (one_process) {
> @@ -920,7 +922,7 @@
>  {
>      int i;
>
> -    for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
> +    for (i = 0; number_to_start && i < ap_scoreboard_image->global.ap_daemons_limit;
++i) {
>   if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
>       continue;
>   }
> @@ -964,10 +966,10 @@
>      total_non_dead = 0;
>
>      ap_sync_scoreboard_image();
> -    for (i = 0; i < ap_daemons_limit; ++i) {
> +    for (i = 0; i < ap_scoreboard_image->global.ap_daemons_limit; ++i) {
>   int status;
>
> - if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate)
> + if (i >= ap_scoreboard_image->global.ap_max_daemons_limit && free_length
==
idle_spawn_rate)
>       break;
>   ws = &ap_scoreboard_image->servers[i][0];
>   status = ws->status;
> @@ -1000,8 +1002,8 @@
>       last_non_dead = i;
>   }
>      }
> -    ap_max_daemons_limit = last_non_dead + 1;
> -    if (idle_count > ap_daemons_max_free) {
> +    ap_scoreboard_image->global.ap_max_daemons_limit = last_non_dead + 1;
> +    if (idle_count > ap_scoreboard_image->global.ap_daemons_max_free) {
>   /* kill off one child... we use the pod because that'll cause it to
>   * shut down gracefully, in case it happened to pick up a request
>   * while we were counting
> @@ -1009,7 +1011,7 @@
>   ap_mpm_pod_signal(pod);
>   idle_spawn_rate = 1;
>      }
> -    else if (idle_count < ap_daemons_min_free) {
> +    else if (idle_count < ap_scoreboard_image->global.ap_daemons_min_free) {
>   /* terminate the free list */
>   if (free_length == 0) {
>       /* only report this condition once */
> @@ -1110,9 +1112,13 @@
>          return 1;
>      }
>
> +    if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */
> + ap_daemons_max_free = ap_daemons_min_free + 1;
> +
>      SAFE_ACCEPT(accept_mutex_init(pconf));
>      if (!is_graceful) {
>          ap_create_scoreboard(pconf, SB_SHARED);
> +        ap_run_setup_shared_info(pconf, plog, s);
>      }
>  #ifdef SCOREBOARD_FILE
>      else {
> @@ -1123,9 +1129,6 @@
>
>      set_signals();
>
> -    if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */
> - ap_daemons_max_free = ap_daemons_min_free + 1;
> -
>      /* If we're doing a graceful_restart then we're going to see a lot
>   * of children exiting immediately when we get into the main loop
>   * below (because we just sent them SIGWINCH).  This happens pretty
> @@ -1135,8 +1138,8 @@
>   * supposed to start up without the 1 second penalty between each fork.
>   */
>      remaining_children_to_start = ap_daemons_to_start;
> -    if (remaining_children_to_start > ap_daemons_limit) {
> - remaining_children_to_start = ap_daemons_limit;
> +    if (remaining_children_to_start > ap_scoreboard_image->global.ap_daemons_limit)
{
> + remaining_children_to_start = ap_scoreboard_image->global.ap_daemons_limit;
>      }
>      if (!is_graceful) {
>   startup_children(remaining_children_to_start);
> @@ -1176,7 +1179,7 @@
>   (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(child_slot), SERVER_DEAD,
>       (request_rec *) NULL);
>   if (remaining_children_to_start
> -     && child_slot < ap_daemons_limit) {
> +     && child_slot < ap_scoreboard_image->global.ap_daemons_limit) {
>       /* we're still doing a 1-for-1 replacement of dead
>   * children with new children
>   */
> @@ -1267,7 +1270,7 @@
>      ap_scoreboard_image->global.running_generation = ap_my_generation;
>      update_scoreboard_global();
>
> -    for (index = 0; index < ap_daemons_limit; ++index) {
> +    for (index = 0; index < ap_scoreboard_image->global.ap_daemons_limit; ++index)
{
>          ap_scoreboard_image->parent[index].process_status = SB_IDLE_DIE;
>      }
>
> @@ -1276,7 +1279,7 @@
>       "Graceful restart requested, doing restart");
>
>   /* kill off the idle ones */
> -        ap_mpm_pod_killpg(pod, ap_daemons_limit);
> +        ap_mpm_pod_killpg(pod, ap_scoreboard_image->global.ap_daemons_limit);
>
>  #ifndef SCOREBOARD_FILE
>   /* This is mostly for debugging... so that we know what is still
> @@ -1285,7 +1288,7 @@
>       * corruption too easily.
>       */
>   ap_sync_scoreboard_image();
> - for (index = 0; index < ap_daemons_limit; ++index) {
> + for (index = 0; index < ap_scoreboard_image->global.ap_daemons_limit; ++index)
{
>       if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
>   ap_scoreboard_image->servers[index][0].status = SERVER_GRACEFUL;
>       }
> @@ -1339,6 +1342,15 @@
>      apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
>  }
>
> +static void prefork_init_shared(apr_pool_t *pconf, apr_pool_t *plog, server_rec *s)
> +{
> +    ap_scoreboard_image->global.ap_max_daemons_limit = -1;
> +    ap_scoreboard_image->global.ap_daemons_limit = ap_daemons_limit;
> +    ap_scoreboard_image->global.ap_daemons_max_free = ap_daemons_max_free;
> +    ap_scoreboard_image->global.ap_daemons_min_free = ap_daemons_min_free;
> +    ap_scoreboard_image->global.ap_max_requests_per_child = ap_max_requests_per_child;
> +}
> +
>  static void prefork_hooks(apr_pool_t *p)
>  {
>  #ifdef AUX3
> @@ -1346,6 +1358,7 @@
>  #endif
>
>      ap_hook_pre_config(prefork_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
> +    ap_hook_setup_shared_info(prefork_init_shared, NULL, NULL, APR_HOOK_MIDDLE);
>  }
>
>  static const char *set_pidfile(cmd_parms *cmd, void *dummy, const char *arg)
> diff -ru ../httpd-2.0/server/scoreboard.c ./server/scoreboard.c
> --- ../httpd-2.0/server/scoreboard.c Mon May 21 18:31:12 2001
> +++ ./server/scoreboard.c Tue Jul  3 13:30:35 2001
> @@ -84,6 +84,14 @@
>  AP_DECLARE_DATA int ap_extended_status = 0;
>  AP_DECLARE_DATA apr_time_t ap_restart_time = 0;
>
> +APR_HOOK_STRUCT(
> +                   APR_HOOK_LINK(setup_shared_info)
> +)
> +
> +AP_IMPLEMENT_HOOK_VOID(setup_shared_info,
> +                       (apr_pool_t *pconf, apr_pool_t *plog, server_rec *s),
> +                       (pconf,plog,s))
> +
>  #if APR_HAS_SHARED_MEMORY
>  #include "apr_shmem.h"
>  static apr_shmem_t *scoreboard_shm = NULL;
>
>


Mime
View raw message