成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網
最全最豐富的資訊網站

Nginx解讀內置非默認模塊 ngx_http_stub_status_module

1 Background

http://nginx.org/en/docs/http/ngx_http_stub_status_module.html

ngx_http_stub_status_module 是一個 Nginx 的內置 HTTP 模塊,該模塊可以提供 Nginx 的狀態信息。默認情況下這個模塊是不被編譯進來的,所以在編譯 Nginx 時要指定加載該模塊:

--with-http_stub_status_module

為什么拿它做例子?因為它也是個足夠短小精悍的模塊,是一個典型 handler 模塊。那么以后我們講解模塊的過程,都是:

  1. 簡要的介紹
  2. 使用的實例
  3. 指令介紹
  4. 源碼分析

2 Simple example

location /nginx_status {    stub_status on;    access_log   off;
access_log /usr/local/nginx/logs/status.log;    #日志 allow SOME.IP.ADD.RESS; deny all; }

我們假設你是在本機上實驗,并且開啟的是 80 端口,那么在瀏覽器中輸入:

http://localhost/nginx_status  

會看到這樣的信息:

Active connections: 291  server accepts handled requests    16630948 16630948 31070465  Reading: 6 Writing: 179 Waiting: 106  

其含義很容易理解:

  • 第一行
    • 當前的活躍連接數:291
  • 第二行
    • 服務器已接受的連接數:16630948(accepted connection #)
    • 服務器已處理的連接數:16630948(handled connection #)
    • 服務器已處理的請求:31070465(可以算出,平均每個連接有 1.8 個請求)(handled connection #)
  • 第三行
    • Reading – Nginx 讀取的請求頭次數為 6;
    • Writting – Nginx 讀取請求體、處理請求并發送響應給客戶端的次數為 179;
    • Waiting – 當前活動的長連接數:106。

Nginx 官方的解釋如下:

  • active connections – number of all open connections
  • server accepts handled requests – nginx accepted 16630948 connections, handled 16630948 connections (no one was closed just it was accepted), and handles 31070465 requests (1.8 requests per connection)
  • reading – nginx reads request header
  • writing – nginx reads request body, processes request, or writes response to a client
  • waiting – keep-alive connections, actually it is active – (reading + writing)

3 Directives

這個模塊中的唯一一個指令,是:

stub_status  
  • 語法:stub_status on
  • 作用域:location
  • 功能:統計這個 location 的信息。

4 Source analysis

先看完整代碼:

/*   * Copyright (C) Igor Sysoev   * Copyright (C) Nginx, Inc.   */      #include <ngx_config.h>  #include <ngx_core.h>  #include <ngx_http.h>      static char *ngx_http_set_status(ngx_conf_t *cf, ngx_command_t *cmd,                                   void *conf);    static ngx_command_t  ngx_http_status_commands[] = {        { ngx_string("stub_status"),        NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,        ngx_http_set_status,        0,        0,        NULL },          ngx_null_command  };        static ngx_http_module_t  ngx_http_stub_status_module_ctx = {      NULL,                                  /* preconfiguration */      NULL,                                  /* postconfiguration */        NULL,                                  /* create main configuration */      NULL,                                  /* init main configuration */        NULL,                                  /* create server configuration */      NULL,                                  /* merge server configuration */        NULL,                                  /* create location configuration */      NULL                                   /* merge location configuration */  };      ngx_module_t  ngx_http_stub_status_module = {      NGX_MODULE_V1,      &ngx_http_stub_status_module_ctx,      /* module context */      ngx_http_status_commands,              /* module directives */      NGX_HTTP_MODULE,                       /* module type */      NULL,                                  /* init master */      NULL,                                  /* init module */      NULL,                                  /* init process */      NULL,                                  /* init thread */      NULL,                                  /* exit thread */      NULL,                                  /* exit process */      NULL,                                  /* exit master */      NGX_MODULE_V1_PADDING  };      static ngx_int_t ngx_http_status_handler(ngx_http_request_t *r)  {      size_t             size;      ngx_int_t          rc;      ngx_buf_t         *b;      ngx_chain_t        out;      ngx_atomic_int_t   ap, hn, ac, rq, rd, wr;        if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {          return NGX_HTTP_NOT_ALLOWED;      }        rc = ngx_http_discard_request_body(r);        if (rc != NGX_OK) {          return rc;      }        ngx_str_set(&r->headers_out.content_type, "text/plain");        if (r->method == NGX_HTTP_HEAD) {          r->headers_out.status = NGX_HTTP_OK;            rc = ngx_http_send_header(r);            if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {              return rc;          }      }        size = sizeof("Active connections:  n") + NGX_ATOMIC_T_LEN             + sizeof("server accepts handled requestsn") - 1             + 6 + 3 * NGX_ATOMIC_T_LEN             + sizeof("Reading:  Writing:  Waiting:  n") + 3 * NGX_ATOMIC_T_LEN;        b = ngx_create_temp_buf(r->pool, size);      if (b == NULL) {          return NGX_HTTP_INTERNAL_SERVER_ERROR;      }        out.buf = b;      out.next = NULL;        ap = *ngx_stat_accepted;      hn = *ngx_stat_handled;      ac = *ngx_stat_active;      rq = *ngx_stat_requests;      rd = *ngx_stat_reading;      wr = *ngx_stat_writing;        b->last = ngx_sprintf(b->last, "Active connections: %uA n", ac);        b->last = ngx_cpymem(b->last, "server accepts handled requestsn",                           sizeof("server accepts handled requestsn") - 1);        b->last = ngx_sprintf(b->last, " %uA %uA %uA n", ap, hn, rq);        b->last = ngx_sprintf(b->last, "Reading: %uA Writing: %uA Waiting: %uA n",                            rd, wr, ac - (rd + wr));        r->headers_out.status = NGX_HTTP_OK;      r->headers_out.content_length_n = b->last - b->pos;        b->last_buf = 1;        rc = ngx_http_send_header(r);        if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {          return rc;      }        return ngx_http_output_filter(r, &out);  }      static char *ngx_http_set_status(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)  {      ngx_http_core_loc_conf_t  *clcf;        clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);      clcf->handler = ngx_http_status_handler;        return NGX_CONF_OK;  }  

的確夠短小精悍吧?關鍵在于 Nginx 提供的模塊擴展方式比較好,讓你可以少寫一些代碼(NDK 可以讓你寫的更少,這是后話)。

4.1 模塊定義 ngx_http_stub_status_module

ngx_module_t  ngx_http_stub_status_module = {      NGX_MODULE_V1,      &ngx_http_stub_status_module_ctx,      /* module context */      ngx_http_status_commands,              /* module directives */      NGX_HTTP_MODULE,                       /* module type */      NULL,                                  /* init master */      NULL,                                  /* init module */      NULL,                                  /* init process */      NULL,                                  /* init thread */      NULL,                                  /* exit thread */      NULL,                                  /* exit process */      NULL,                                  /* exit master */      NGX_MODULE_V1_PADDING  };  

與此前介紹的 ngx_http_hello_world_module 并無本質區別。

4.2 命令集定義 ngx_http_status_commands

static ngx_command_t  ngx_http_status_commands[] = {        { ngx_string("stub_status"),        NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,        ngx_http_set_status,        0,        0,        NULL },          ngx_null_command  };  

命令集定義如上,得到如下信息:

  • name:stub_status
  • type:server conf、location conf、conf flag,其中最后一個比較陌生,相似的取值有:
    • #define NGX_CONF_ARGS_NUMBER 0x000000ff
    • #define NGX_CONF_BLOCK 0x00000100
    • #define NGX_CONF_FLAG 0x00000200
    • #define NGX_CONF_ANY 0x00000400
    • #define NGX_CONF_1MORE 0x00000800
    • #define NGX_CONF_2MORE 0x00001000
    • #define NGX_CONF_MULTI 0x00002000
  • set:ngx_http_set_status

下面解釋下一些 types:

4.2.1 NGX_CONF_XXX

以下宏定義來自 ngx_conf_file.h:

#define NGX_CONF_NOARGS      0x00000001 // 命令不接受參數  #define NGX_CONF_TAKE1       0x00000002 // 命令攜帶1個參數  #define NGX_CONF_TAKE2       0x00000004 // 命令攜帶2個參數  #define NGX_CONF_TAKE3       0x00000008 // 命令攜帶3個參數  #define NGX_CONF_TAKE4       0x00000010 // 命令攜帶4個參數  #define NGX_CONF_TAKE5       0x00000020 // 命令攜帶5個參數  #define NGX_CONF_TAKE6       0x00000040 // 命令攜帶6個參數  #define NGX_CONF_TAKE7       0x00000080 // 命令攜帶7個參數    #define NGX_CONF_TAKE12      (NGX_CONF_TAKE1|NGX_CONF_TAKE2) // 命令攜帶1個或2個參數  #define NGX_CONF_TAKE13      (NGX_CONF_TAKE1|NGX_CONF_TAKE3) // 命令攜帶1個或3個參數  #define NGX_CONF_TAKE23      (NGX_CONF_TAKE2|NGX_CONF_TAKE3) // 命令攜帶2個或3個參數  #define NGX_CONF_TAKE123     (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3) // 命令攜帶1個、2個或3個參數  #define NGX_CONF_TAKE1234    (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3|NGX_CONF_TAKE4) // 命令攜帶1個、2個、3個或4個參數    #define NGX_CONF_ARGS_NUMBER 0x000000ff // 命令  #define NGX_CONF_BLOCK       0x00000100 // 塊域,后面跟 {…},比如 server {...}  #define NGX_CONF_FLAG        0x00000200 // 命令接受“on|off”參數  #define NGX_CONF_ANY         0x00000400  #define NGX_CONF_1MORE       0x00000800 // 命令攜帶至少1個參數  #define NGX_CONF_2MORE       0x00001000 // 命令攜帶至少2個參數  #define NGX_CONF_MULTI       0x00002000 // 命令攜帶多個參數  

4.3 上下文定義 ngx_http_stub_status_module_ctx

static ngx_http_module_t  ngx_http_stub_status_module_ctx = {      NULL,                                  /* preconfiguration */      NULL,                                  /* postconfiguration */        NULL,                                  /* create main configuration */      NULL,                                  /* init main configuration */        NULL,                                  /* create server configuration */      NULL,                                  /* merge server configuration */        NULL,                                  /* create location configuration */      NULL                                   /* merge location configuration */  };  

這個都是 NULL,夠簡單,無話可說了??

4.4 命令設置函數 ngx_http_set_status

static char *ngx_http_set_status(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {        ngx_http_core_loc_conf_t  *clcf;        clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);      clcf->handler = ngx_http_status_handler;        return NGX_CONF_OK;  }  

和 ngx_http_hello_world_module 對比下:

static char* ngx_http_hello_world(ngx_conf_t* cf, ngx_command_t* cmd, void* conf) {        ngx_http_core_loc_conf_t* clcf;        clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);      clcf->handler = ngx_http_hello_world_handler;        ngx_conf_set_str_slot(cf, cmd, conf);        return NGX_CONF_OK;  }  

唯一的區別,就是 ngx_http_hello_world_module 多了一句 ngx_conf_set_str_slot。這個先留做一個問題,后面會介紹,暫時與關鍵主題無關。

4.5 命令處理函數 ngx_http_status_handler

static ngx_int_t ngx_http_status_handler(ngx_http_request_t *r)  {      size_t             size;      ngx_int_t          rc;      ngx_buf_t         *b;      ngx_chain_t        out;      ngx_atomic_int_t   ap, hn, ac, rq, rd, wr;  

這個模塊要求接受的請求類是 GET、HEAD,其他類型的請求會被拒絕。

    if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {          return NGX_HTTP_NOT_ALLOWED;      }  

放棄請求體,因為這個模塊用不上。

    rc = ngx_http_discard_request_body(r);        if (rc != NGX_OK) {          return rc;      }  

如果請求是 HEAD 類型的,則直接設置響應頭的 content_type、status 字段,并發送響應頭。

    ngx_str_set(&r->headers_out.content_type, "text/plain");        if (r->method == NGX_HTTP_HEAD) {          r->headers_out.status = NGX_HTTP_OK;            rc = ngx_http_send_header(r);            if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {              return rc;          }      }  

創建一個緩沖區,向緩沖區寫入我們上面在瀏覽器中看到的東西。

    size = sizeof("Active connections:  n") + NGX_ATOMIC_T_LEN             + sizeof("server accepts handled requestsn") - 1             + 6 + 3 * NGX_ATOMIC_T_LEN             + sizeof("Reading:  Writing:  Waiting:  n") + 3 * NGX_ATOMIC_T_LEN;        b = ngx_create_temp_buf(r->pool, size);      if (b == NULL) {          return NGX_HTTP_INTERNAL_SERVER_ERROR;      }        out.buf = b;      out.next = NULL;        ap = *ngx_stat_accepted;      hn = *ngx_stat_handled;      ac = *ngx_stat_active;      rq = *ngx_stat_requests;      rd = *ngx_stat_reading;      wr = *ngx_stat_writing;        // 封裝了 sprintf      b->last = ngx_sprintf(b->last, "Active connections: %uA n", ac);        // 封裝了 memcpy      b->last = ngx_cpymem(b->last, "server accepts handled requestsn",                           sizeof("server accepts handled requestsn") - 1);        b->last = ngx_sprintf(b->last, " %uA %uA %uA n", ap, hn, rq);        b->last = ngx_sprintf(b->last, "Reading: %uA Writing: %uA Waiting: %uA n",                            rd, wr, ac - (rd + wr));  

緩沖區寫完了。然后設置下響應頭的 status、content_length_n(還記得嗎?b->last – b->pos 剛好是緩沖區的第二個區域,是已寫入數據部分。)

    r->headers_out.status = NGX_HTTP_OK;      r->headers_out.content_length_n = b->last - b->pos;        b->last_buf = 1;  

發送響應頭。

    rc = ngx_http_send_header(r);        if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {          return rc;      }  

filter。

    return ngx_http_output_filter(r, &out);  }  
贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
亚洲GAY片在线GV网站| 久久人搡人人玩人妻精品| 9精产国品一二三产区| 99国精产品灬源码168| 中文国产成人精品久久| 亚洲AV永久无码精品无码一区二区| 亚洲AⅤ永久无码毛片牛牛影视| 熟妇人妻不卡中文字幕| 日文中文字幕乱码一二三区别| 色欲久久久天天天综合网| 无码网站天天爽免费看视频| 亚洲AV无码一区二区三区大黄瓜| 亚洲精品无码专区在线观看| 亚洲鲁丝片一区二区三区| 一本久久A精品一区二区| 亚洲乱理伦片在线观看中字| 在公交上被灌满白浆的视频| YIN荡到骨子里的SAO货| CHINESE熟女熟妇1乱| 超碰人人看人人2017| 国产黄在线观看免费观看不卡| 国产在线视频 | 传媒| 激情内射人妻1区2区3区| 久久亚洲中文字幕精品有坂深雪 | 欧美精品黑人粗大视频| 没有被爱过的女人| 日产精品1区2区3区| 无码H肉动漫在线观看| 亚洲国产精品一区二区成人片| 余生请多指教在线观看免费全集 | 亚洲AV日韩AⅤ永久无码| 亚洲AV实录无码成人精品电影| 亚洲国产精品无码久久98蜜桃| 在办公室被C到呻吟的动态图| 啊灬啊灬啊灬快好深| 国产精品免费AⅤ片在线观看| 精品人妻一区二区三区四区在线| 妺妺窝人体色聚窝窝| 人妻AV综合天堂一区| 武侠 欧美 另类 人妻| 一二三四免费观看视频中国| 插花弄玉小说荔枝很甜| 国产最新AV在线播放不卡| 免费人成网站在线观看欧美| 熟妇人妻无码中文字幕老熟妇| 亚洲欧洲精品成人久久曰| BBW大屁股肥臀妇女ASS| 高潮爽死抽搐白浆GIF视频| 精品无码专区免费下载| 人妻无码熟妇乱又视频| 亚洲AV无码一区东京热| AAA女人18毛片水真多| 国产精品永久久久久久久久久| 久久综合伊人77777| 十八禁无码免费网站| 野花新免费高清完整在线观看| 97人妻碰碰视频免费上线| 国产精品国产免费无码专区蜜桃| 久久婷婷人人澡人人爽人人爱| 少妇被黑人到高潮喷出白浆| 性无码专区一色吊丝中文字幕 | 久久人午夜亚洲精品无码区| 日韩人妻在线一区二区三区 | 狠狠躁夜夜躁人人爽天天古典 | 国产A∨国片精品青草视频| 黑人巨茎大战俄罗斯美女| 男女乱婬免费视频黑人| 五月综合网亚洲乱妇久久| 在线无码VA中文字幕无码| 国产精品久久国产三级国不卡顿| 美国ZOOM人与ZOOM视频| 午夜精品无人区乱码1区2区| 88国产精品欧美一区二区三区| 国产精品亚洲专区无码破解版| 内射无码专区久久亚洲| 亚洲AV无码不卡国产精品| GAY成年男人露J网站| 精品熟女少妇AⅤ免费久久| 日欧 片内射AV在线影院| 又湿又紧又大又爽A视频男| 国产VA免费精品高清在线观看| 伦人伦XXX国产对白| 新妺妺窝人体色7777婷婷| 八戒八戒视频在线WWW观看 | 中国大陆女RAPPER欢迎你| 国产久热精品无码激情| 亲生乖女好紧H下| 一二三四在线观看免费中文| 国产欧美久久一区二区 | JAVAPARSER乱偷| 久久久久久精品毛片A级蜜桃| 玩弄秘书的奶又大又软| 办公室被公司领导C了很多次| 老熟女太熟了95AV| 亚洲爆乳成AV人在线蜜芽| 国产精品乱码久久久久久软件| 日韩精品一区二区三区中文无码| 97久久人人超碰国产精品| 久久久久久久女国产乱让韩| 亚洲ΑV无码一区二区三区四区| 国产精品久久毛片| 色老头BGMBGMBGM| FREE性玩弄少妇HD| 男人的天堂免费A级毛片无码| 亚洲精品天堂无码中文字幕| 国产一码二码三码区别| 无码国产精品久久一区免费| 放荡爆乳女教师电影在线观看| 日本JAPANESE 30成熟| 99国产精品99久久久久久| 麻豆国产96在线 | 日韩| 一本大道香蕉在线资源| 精品少妇爆乳无码AⅤ区| 亚洲H在线播放在线观看H| 国产日韩精品SUV| 无码性午夜视频在线观看| 关晓彤露内毛黑森林| 色综合天天综合网天天小说 | 日本XXXX裸体XXXX| WBBBB搡BBBB搡BBBB| 欧美丰满美乳XXⅩ高潮| 337P日本欧洲亚洲大胆在线| 毛豆日产精品卡2卡3卡4卡免费 | 浪荡艳妇爆乳JUFD汗だく肉感| 亚洲字幕AV一区二区三区四区| 精品无码国产污污污免费网站国产 | 国产成人三级在线视频网站观看| 色爱无码AⅤ综合区| 俄罗斯人和欧洲人长相区别 | 国产男男GAY做受XXX| 午夜麻豆国产精品无码| 国产人妖视频一区二区| 性一交一无一伦一精一品| 国产亚洲精品自在久久蜜TV| 亚洲AV噜噜在线成人网站| 国产亚洲AV☆浪潮在线观看 | 私人IMAX情侣影院家庭影院| 国产成人无码A区在线| 婷婷妺妺窝人体色www久久| 国产精彩乱子真实视频| 无码少妇一区二区浪潮免费 | 亚洲AV无码卡通动漫AV| 精品久久久久久国产牛牛| 亚洲日韩亚洲另类激情文学| 久久久噜噜噜久久熟女| 18禁无遮挡啪啪摇乳动态图| 欧美黑人乱猛交xX 乂500| XXX片黑人又大又粗又长| 日本成AⅤ人片日本伦| 成人AV无码一区二区三区 | 欧美性生交XXXXX免费观看| 成人欧美一区二区三区1314| 少妇无码太爽了不卡视频在线看| 国产高清在线A视频大全| 无码专区中文字幕无码野外| 哈昂~哈昂够了太多了男男 | 午夜毛片精彩毛片| 黑人精品欧美一区二区蜜桃| 亚洲综合国产成人丁香五月激情| 免费看片A级毛片免费看| W永久939W乳液78| 少女たちよ在线观看动漫在线观看 | 三上悠亚SSⅠN939无码播放| 国产精品嫩草影院永久…| 亚洲AV无码日韩AV无码导航| 久久伊人精品一区二区三区| ASS年轻少妇PIC精品| 日本熟妇XXⅩ浓密黑毛| 国产美女在线精品免费观看| 亚洲日韩一页精品发布| 欧美精品视频一区二区| 国产AV露脸一线国语对白| 亚洲VA国产VA天堂VA久久| 麻豆人人妻人人妻人人片AV| ZOZOTOWN| 午夜精品久久久久久久| 久久综合久久鬼色| 成人免费AV一区二区三区| 亚洲AV成人无码精品网站色欲| 精品久久久久久亚洲综合网 | 国产精品成人AV电影不卡| 亚洲乱码中文论理电影| 内射人妻无套中出无码| 国产9 1在线 | 欧洲| 亚洲精品AV中文字幕在线| 蜜芽久久人人超碰爱香蕉| 成人看片黄APP免费看软件| 性色AV免费观看| 妺妺窝人体色WWW精品| 国产av一区二区三区| 亚洲天天做日日做天天欢| 人妻少妇精品中文字幕AV| 国产午夜精品久久精品电影| 中文字幕无码不卡一区二区三区| 少妇精品久久久一区二区三区| 精品欧美成人高清在线观看| 啊~用力CAO我CAO死我视频| 亚洲AⅤ无码日韩AV中文AV伦| 免费国产AV在线观看| 国产激情一区二区三区|