src/http/modules/ngx_http_degradation_module.c - nginx-1.7.10

Global variables defined

Data types defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_http.h>


  8. typedef struct {
  9.     size_t      sbrk_size;
  10. } ngx_http_degradation_main_conf_t;


  11. typedef struct {
  12.     ngx_uint_t  degrade;
  13. } ngx_http_degradation_loc_conf_t;


  14. static ngx_conf_enum_t  ngx_http_degrade[] = {
  15.     { ngx_string("204"), 204 },
  16.     { ngx_string("444"), 444 },
  17.     { ngx_null_string, 0 }
  18. };


  19. static void *ngx_http_degradation_create_main_conf(ngx_conf_t *cf);
  20. static void *ngx_http_degradation_create_loc_conf(ngx_conf_t *cf);
  21. static char *ngx_http_degradation_merge_loc_conf(ngx_conf_t *cf, void *parent,
  22.     void *child);
  23. static char *ngx_http_degradation(ngx_conf_t *cf, ngx_command_t *cmd,
  24.     void *conf);
  25. static ngx_int_t ngx_http_degradation_init(ngx_conf_t *cf);


  26. static ngx_command_t  ngx_http_degradation_commands[] = {

  27.     { ngx_string("degradation"),
  28.       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
  29.       ngx_http_degradation,
  30.       NGX_HTTP_MAIN_CONF_OFFSET,
  31.       0,
  32.       NULL },

  33.     { ngx_string("degrade"),
  34.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  35.       ngx_conf_set_enum_slot,
  36.       NGX_HTTP_LOC_CONF_OFFSET,
  37.       offsetof(ngx_http_degradation_loc_conf_t, degrade),
  38.       &ngx_http_degrade },

  39.       ngx_null_command
  40. };


  41. static ngx_http_module_t  ngx_http_degradation_module_ctx = {
  42.     NULL,                                  /* preconfiguration */
  43.     ngx_http_degradation_init,             /* postconfiguration */

  44.     ngx_http_degradation_create_main_conf, /* create main configuration */
  45.     NULL,                                  /* init main configuration */

  46.     NULL,                                  /* create server configuration */
  47.     NULL,                                  /* merge server configuration */

  48.     ngx_http_degradation_create_loc_conf/* create location configuration */
  49.     ngx_http_degradation_merge_loc_conf    /* merge location configuration */
  50. };


  51. ngx_module_t  ngx_http_degradation_module = {
  52.     NGX_MODULE_V1,
  53.     &ngx_http_degradation_module_ctx,      /* module context */
  54.     ngx_http_degradation_commands,         /* module directives */
  55.     NGX_HTTP_MODULE,                       /* module type */
  56.     NULL,                                  /* init master */
  57.     NULL,                                  /* init module */
  58.     NULL,                                  /* init process */
  59.     NULL,                                  /* init thread */
  60.     NULL,                                  /* exit thread */
  61.     NULL,                                  /* exit process */
  62.     NULL,                                  /* exit master */
  63.     NGX_MODULE_V1_PADDING
  64. };


  65. static ngx_int_t
  66. ngx_http_degradation_handler(ngx_http_request_t *r)
  67. {
  68.     ngx_http_degradation_loc_conf_t  *dlcf;

  69.     dlcf = ngx_http_get_module_loc_conf(r, ngx_http_degradation_module);

  70.     if (dlcf->degrade && ngx_http_degraded(r)) {
  71.         return dlcf->degrade;
  72.     }

  73.     return NGX_DECLINED;
  74. }


  75. ngx_uint_t
  76. ngx_http_degraded(ngx_http_request_t *r)
  77. {
  78.     time_t                             now;
  79.     ngx_uint_t                         log;
  80.     static size_t                      sbrk_size;
  81.     static time_t                      sbrk_time;
  82.     ngx_http_degradation_main_conf_t  *dmcf;

  83.     dmcf = ngx_http_get_module_main_conf(r, ngx_http_degradation_module);

  84.     if (dmcf->sbrk_size) {

  85.         log = 0;
  86.         now = ngx_time();

  87.         /* lock mutex */

  88.         if (now != sbrk_time) {

  89.             /*
  90.              * ELF/i386 is loaded at 0x08000000, 128M
  91.              * ELF/amd64 is loaded at 0x00400000, 4M
  92.              *
  93.              * use a function address to subtract the loading address
  94.              */

  95.             sbrk_size = (size_t) sbrk(0) - ((uintptr_t) ngx_palloc & ~0x3FFFFF);
  96.             sbrk_time = now;
  97.             log = 1;
  98.         }

  99.         /* unlock mutex */

  100.         if (sbrk_size >= dmcf->sbrk_size) {
  101.             if (log) {
  102.                 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  103.                               "degradation sbrk:%uzM",
  104.                               sbrk_size / (1024 * 1024));
  105.             }

  106.             return 1;
  107.         }
  108.     }

  109.     return 0;
  110. }


  111. static void *
  112. ngx_http_degradation_create_main_conf(ngx_conf_t *cf)
  113. {
  114.     ngx_http_degradation_main_conf_t  *dmcf;

  115.     dmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_degradation_main_conf_t));
  116.     if (dmcf == NULL) {
  117.         return NULL;
  118.     }

  119.     return dmcf;
  120. }


  121. static void *
  122. ngx_http_degradation_create_loc_conf(ngx_conf_t *cf)
  123. {
  124.     ngx_http_degradation_loc_conf_t  *conf;

  125.     conf = ngx_palloc(cf->pool, sizeof(ngx_http_degradation_loc_conf_t));
  126.     if (conf == NULL) {
  127.         return NULL;
  128.     }

  129.     conf->degrade = NGX_CONF_UNSET_UINT;

  130.     return conf;
  131. }


  132. static char *
  133. ngx_http_degradation_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
  134. {
  135.     ngx_http_degradation_loc_conf_t  *prev = parent;
  136.     ngx_http_degradation_loc_conf_t  *conf = child;

  137.     ngx_conf_merge_uint_value(conf->degrade, prev->degrade, 0);

  138.     return NGX_CONF_OK;
  139. }


  140. static char *
  141. ngx_http_degradation(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  142. {
  143.     ngx_http_degradation_main_conf_t  *dmcf = conf;

  144.     ngx_str_t  *value, s;

  145.     value = cf->args->elts;

  146.     if (ngx_strncmp(value[1].data, "sbrk=", 5) == 0) {

  147.         s.len = value[1].len - 5;
  148.         s.data = value[1].data + 5;

  149.         dmcf->sbrk_size = ngx_parse_size(&s);
  150.         if (dmcf->sbrk_size == (size_t) NGX_ERROR) {
  151.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  152.                                "invalid sbrk size \"%V\"", &value[1]);
  153.             return NGX_CONF_ERROR;
  154.         }

  155.         return NGX_CONF_OK;
  156.     }

  157.     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  158.                        "invalid parameter \"%V\"", &value[1]);

  159.     return NGX_CONF_ERROR;
  160. }


  161. static ngx_int_t
  162. ngx_http_degradation_init(ngx_conf_t *cf)
  163. {
  164.     ngx_http_handler_pt        *h;
  165.     ngx_http_core_main_conf_t  *cmcf;

  166.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

  167.     h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
  168.     if (h == NULL) {
  169.         return NGX_ERROR;
  170.     }

  171.     *h = ngx_http_degradation_handler;

  172.     return NGX_OK;
  173. }