Nginx源碼分析 - HTTP模組篇 - ngx_http_block函數和HTTP模組的初始化

來源:互聯網
上載者:User

前面幾章整理了Nginx的事件模組,這一章開始整理HTTP模組。

HTTP模組的初始化工作,都在src/http/nginx_http.c 中的ngx_http_block函數中進行的。
http模組的配置

在看nginx_http_block之前,我們還必須看一下nginx.conf中 HTTP大模組的設定檔,只有理解了HTTP模組的配置,才能更好的理解HTTP模組如何初始化的。

配置如下:

http {  include       mime.types;  default_type  application/octet-stream;  #charset  gb2312;        server_names_hash_bucket_size 128;  client_header_buffer_size 32k;  large_client_header_buffers 4 32k;  client_max_body_size 8m;        sendfile on;  tcp_nopush     on;  keepalive_timeout 60;  tcp_nodelay on;  fastcgi_connect_timeout 300;  fastcgi_send_timeout 300;  fastcgi_read_timeout 300;  fastcgi_buffer_size 64k;  fastcgi_buffers 4 64k;  fastcgi_busy_buffers_size 128k;  fastcgi_temp_file_write_size 128k;  gzip on;  gzip_min_length  1k;  gzip_buffers     4 16k;  gzip_http_version 1.0;  gzip_comp_level 2;  gzip_types       text/plain application/x-javascript text/css application/xml;  gzip_vary on;  #limit_zone  crawler  $binary_remote_addr  10m;  server  {    listen       80;    #server_name  blog.s135.com;    index index.html index.htm index.php;    root   /home/wwwroot/;    #limit_conn   crawler  20;                                     location ~ .*\.(php|php5)?$    {            #fastcgi_pass  unix:/tmp/php-cgi.sock;      fastcgi_pass  127.0.0.1:9000;      fastcgi_index index.php;      include fcgi.conf;    }        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$    {      expires      30d;    }    location ~ .*\.(js|css)?$    {      expires      1h;    }        log_format  access  '$remote_addr - $remote_user [$time_local] "$request" '              '$status $body_bytes_sent "$http_referer" '              '"$http_user_agent" $http_x_forwarded_for';    access_log  /usr/local/nginx-1.4.7/logs/access.log  access;      }  server  {    listen  80;    server_name  status.blog.s135.com;    location / {    stub_status on;    access_log   off;    }  }

從上面的設定檔我們可以看到,HTTP的配置主要分為4層:

1. 最外層的http{} 模組。模組類型:NGX_CORE_MODULE (最外層的核心模組)

2. http核心模組中的main配置:http{include mine type; }。模組類型:NGX_HTTP_MODULE (全域的HTTP模組的配置資訊)

3. http核心模組中的server配置:server{}。模組類型:NGX_HTTP_MODULE (主要是配置Server的資訊)

4. http核心模組中的location本地資訊配置:location{}。模組類型:NGX_HTTP_MODULE (主要一個server對應的本地資源資訊:靜態資源、反向 Proxy連接埠地址、各種語言容器連接埠等)

最外層的http模組,類型NGX_CORE_MODULE,屬於核心模組,核心模組在最開始設定檔初始化的時候,就會調用指令的命令集。所以在核心模組啟動的時候就會調用http的模組配置解析指令函數:ngx_http_block


HTTP核心模組的資料結構

/** * HTTP模組命令集 * HTTP模組也是一個大模組,最外層為: * http { * .... * } * ngx_http_block:該方法就是回呼函數 * HTTP核心模組 */static ngx_command_t  ngx_http_commands[] = {    { ngx_string("http"),      NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,      ngx_http_block,      0,      0,      NULL },      ngx_null_command};/** *HTTP核心模組上下文 */static ngx_core_module_t  ngx_http_module_ctx = {    ngx_string("http"),    NULL,    NULL};/** * HTTP核心模組 結構 * 模組類型:NGX_CORE_MODULE * 通過調用ngx_http_block方法,解析{}中的HTTP模組配置 */ngx_module_t  ngx_http_module = {    NGX_MODULE_V1,    &ngx_http_module_ctx,                  /* module context */    ngx_http_commands,                     /* module directives */    NGX_CORE_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};

從上面的結構中可以看到http{} 是NGX_CORE_MODULE,在核心模組初始化的時候,會調用ngx_http_commands命令集中的回呼函數,逐個解析核心模組的配置資訊。

而HTTP模組的總入口就是這個http{}命令集的回呼函數:ngx_http_block

如果對設定檔如何解析有遺忘,請回顧《 Nginx源碼分析 - 主流程篇 - 解析設定檔 》


ngx_http_block函數詳解

/** *ngx_http_commands 命令集的回呼函數 *HTTP模組初始化的入口函數 * */static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf){    char                        *rv;    ngx_uint_t                   mi, m, s;    ngx_conf_t                   pcf;    ngx_http_module_t           *module;    ngx_http_conf_ctx_t         *ctx;    ngx_http_core_loc_conf_t    *clcf;    ngx_http_core_srv_conf_t   **cscfp;    ngx_http_core_main_conf_t   *cmcf;    if (*(ngx_http_conf_ctx_t **) conf) {        return "is duplicate";    }    /* the main http context */    /* 分配一塊記憶體,存放http配置上下文 */    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));    if (ctx == NULL) {        return NGX_CONF_ERROR;    }    *(ngx_http_conf_ctx_t **) conf = ctx;    /* count the number of the http modules and set up their indices */    /* 計算http模組個數 */    ngx_http_max_module = ngx_count_modules(cf->cycle, NGX_HTTP_MODULE);    /* the http main_conf context, it is the same in the all http contexts */    /**     * 最外層的HTTP配置     * http  {  include       mime.types;  default_type  application/octet-stream;     */    ctx->main_conf = ngx_pcalloc(cf->pool,                                 sizeof(void *) * ngx_http_max_module);    if (ctx->main_conf == NULL) {        return NGX_CONF_ERROR;    }    /*     * the http null srv_conf context, it is used to merge     * the server{}s' srv_conf's     */    /**     * server層的配置     *   server  {    listen       80;    #server_name  blog.s135.com;    index index.html index.htm index.php;    root   /home/wwwroot/;     */    ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);    if (ctx->srv_conf == NULL) {        return NGX_CONF_ERROR;    }    /*     * the http null loc_conf context, it is used to merge     * the server{}s' loc_conf's     */    /**     * location 層的配置    location ~ .*\.(php|php5)?$    {      #fastcgi_pass  unix:/tmp/php-cgi.sock;      fastcgi_pass  127.0.0.1:9000;      fastcgi_index index.php;      include fcgi.conf;    }     */    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);    if (ctx->loc_conf == NULL) {        return NGX_CONF_ERROR;    }    /*     * create the main_conf's, the null srv_conf's, and the null loc_conf's     * of the all http modules     */     /**      * 調用:create_main_conf、create_srv_conf、create_loc_conf      * 建立配置      */    for (m = 0; cf->cycle->modules[m]; m++) {        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {            continue;        }        module = cf->cycle->modules[m]->ctx;        mi = cf->cycle->modules[m]->ctx_index;        if (module->create_main_conf) {            ctx->main_conf[mi] = module->create_main_conf(cf);            if (ctx->main_conf[mi] == NULL) {                return NGX_CONF_ERROR;            }        }        if (module->create_srv_conf) {            ctx->srv_conf[mi] = module->create_srv_conf(cf);            if (ctx->srv_conf[mi] == NULL) {                return NGX_CONF_ERROR;            }        }        if (module->create_loc_conf) {            ctx->loc_conf[mi] = module->create_loc_conf(cf);            if (ctx->loc_conf[mi] == NULL) {                return NGX_CONF_ERROR;            }        }    }    pcf = *cf;    cf->ctx = ctx;    /**     * preconfiguration 預先初始化配置資訊     */    for (m = 0; cf->cycle->modules[m]; m++) {        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {            continue;        }        module = cf->cycle->modules[m]->ctx;        if (module->preconfiguration) {            if (module->preconfiguration(cf) != NGX_OK) {                return NGX_CONF_ERROR;            }        }    }    /* parse inside the http{} block */    cf->module_type = NGX_HTTP_MODULE;    cf->cmd_type = NGX_HTTP_MAIN_CONF;    rv = ngx_conf_parse(cf, NULL);    if (rv != NGX_CONF_OK) {        goto failed;    }    /*     * init http{} main_conf's, merge the server{}s' srv_conf's     * and its location{}s' loc_conf's     */    /**     * 初始化main配置     * 合并 server srv_conf     * 合并location loc_conf     */    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];    cscfp = cmcf->servers.elts;    for (m = 0; cf->cycle->modules[m]; m++) {        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {            continue;        }        module = cf->cycle->modules[m]->ctx;        mi = cf->cycle->modules[m]->ctx_index;        /* init http{} main_conf's */        if (module->init_main_conf) {            rv = module->init_main_conf(cf, ctx->main_conf[mi]);            if (rv != NGX_CONF_OK) {                goto failed;            }        }        rv = ngx_http_merge_servers(cf, cmcf, module, mi);        if (rv != NGX_CONF_OK) {            goto failed;        }    }    /* create location trees */    /**     * 建立 location模組的trees     */    for (s = 0; s < cmcf->servers.nelts; s++) {        clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];        if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {            return NGX_CONF_ERROR;        }        if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {            return NGX_CONF_ERROR;        }    }    if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {        return NGX_CONF_ERROR;    }    if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {        return NGX_CONF_ERROR;    }    for (m = 0; cf->cycle->modules[m]; m++) {        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {            continue;        }        module = cf->cycle->modules[m]->ctx;        if (module->postconfiguration) {            if (module->postconfiguration(cf) != NGX_OK) {                return NGX_CONF_ERROR;            }        }    }    if (ngx_http_variables_init_vars(cf) != NGX_OK) {        return NGX_CONF_ERROR;    }    /*     * http{}'s cf->ctx was needed while the configuration merging     * and in postconfiguration process     */    *cf = pcf;    if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {        return NGX_CONF_ERROR;    }    /* optimize the lists of ports, addresses and server names */    /* ngx_http_optimize_servers 初始化listen 連接埠號碼 ip地址 伺服器等監聽資訊*/    if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {        return NGX_CONF_ERROR;    }    return NGX_CONF_OK;failed:    *cf = pcf;    return rv;}

下一章會詳細講解: ngx_http_optimize_servers



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.