Nginx http的初始化(一)

来源:互联网 发布:2k17库里捏脸数据 编辑:程序博客网 时间:2024/05/22 13:16

其实经过前面文章的分析,我们已经知道在Nginx启动的时候会先进行core类型模块的处理。在Nginx的每一部分都会有一个core类型的模块与之对应,在解析配置文件的时候,这些core类型的模块便是这些他们所代表的部分的入口。例如event部分,ngx_events_module模块就是一个core类型的模块,因而我们可以看到event部分的初始化其实是从ngx_events_module模块的命令events的set回调函数开始的。

另外在每一部分都有一个比较重要的核心模块,例如event部分有ngx_event_core_module模块,其虽然只是一个event类型的模块,但是其却处理了event部分的大多数命令,而且它的配置结构也会保存很多十分重要的信息,例如ngx_event_core_module的配置结构ngx_event_conf_t就保存了event是否使用互斥信号,具体使用哪一个时间模块的等信息。其实要分析nginx每一部分就应该从这两个模块开始。

好了,那么就按照上面的说法来分析http部分吧,先找到core类型的模块,它是ngx_http_module模块,其定义如下:

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};static ngx_core_module_t  ngx_http_module_ctx = {    ngx_string("http"),    NULL,    NULL};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};
我们可以看到ngx_http_module模块只有一个命令,那就是http,其的set回调函数式ngx_http_block函数。

(嗯,这个地方要插入一个话题,我们知道每种类型的模块的配置结构并不是保存在模块内部的,我们可以看到全局cycle变量有一个域是ctx,它用来保存“所有”模块的配置结构上下文,这里用引号是有道理的。其实ctx只是保存了每一部分core类型的模块的配置结构,然后再用core类型模块的配置结构来保存其所在部分的其余具体模块的配置结构,然后其余具体模块想要获取其的配置,就得先找到代表它的core类型的模块,进而才能找到其的配置结构。也就是说模块的配置结构的保存其实是按照层次来进行的,嗯,这个部分以后干脆写一篇文章来说明吧,这个比较关键,如果不搞透彻的话,对于理解代码会带来很大的问题。)

好了,说了太多的废话,接下来回归http。这里我们来看看http部分是如何来保存其具体模块的配置结构的吧。嗯,http部分还是比较奇葩的。这里要看一下ngx_http_conf_ctx_t这个结构:

//http模块的配置结构的定义typedef struct {    void        **main_conf;  //所有http模块的main config数组(可以把它看成指针的数组)    void        **srv_conf;   //所有http模块的srv config数组    void        **loc_conf;   //所有http模块的 loc config数组} ngx_http_conf_ctx_t;
在全局cycle变量的ctx域的ngx_http_module模块index处将会保存这么一个结构,用它来索引其余所有http类型模块的配置结构。嗯,够奇葩的,也就是说每一个http模块最多有可能有三种配置结构了。

好了。接下开始http部分的核心模块了,它是ngx_http_core_module模块,我们先看一下它的定义:

static ngx_http_module_t  ngx_http_core_module_ctx = {    ngx_http_core_preconfiguration,        /* preconfiguration */    NULL,                                  /* postconfiguration */    ngx_http_core_create_main_conf,        /* create main configuration */    ngx_http_core_init_main_conf,          /* init main configuration */    ngx_http_core_create_srv_conf,         /* create server configuration */    ngx_http_core_merge_srv_conf,          /* merge server configuration */    ngx_http_core_create_loc_conf,         /* create location configuration */    ngx_http_core_merge_loc_conf           /* merge location configuration */};ngx_module_t  ngx_http_core_module = {    NGX_MODULE_V1,    &ngx_http_core_module_ctx,             /* module context */    ngx_http_core_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};
由于其的命令太多了,这里就不贴出来了。只能说那些重要的命令都被这个模块包含了。然后我们在来看看它的配置结构吧,因为其配置结构将会保存http部分许多重要的配置信息。(这货居然三种类型的配置结构都有)我们首先来看它的main_conf(这个很重要):
typedef struct { /**      * 存储所有的ngx_http_core_srv_conf_t,元素的个数等于server块的个数。      */      ngx_array_t                servers;         /* ngx_http_core_srv_conf_t *//**   * 包含所有phase,以及注册的phase handler,这些handler在处理http请求时,   * 会被依次调用,通过ngx_http_phase_handler_t的next字段串联起来组成一个   * 链表。   */      ngx_http_phase_engine_t    phase_engine;    /**      * 以hash存储的所有request header      */      ngx_hash_t                 headers_in_hash;    /**      * 被索引的nginx变量 ,比如通过rewrite模块的set指令设置的变量,会在这个hash      * 中分配空间,而诸如$http_XXX和$cookie_XXX等内建变量不会在此分配空间。      */      ngx_hash_t                 variables_hash;    /**      * ngx_http_variable_t类型的数组,所有被索引的nginx变量被存储在这个数组中。      * ngx_http_variable_t结构中有属性index,是该变量在这个数组的下标。      */      ngx_array_t                variables;       /* ngx_http_variable_t */    ngx_uint_t                 ncaptures;    /**      * server names的hash表的允许的最大bucket数量,默认值是512。      */      ngx_uint_t                 server_names_hash_max_size;    ngx_uint_t                 server_names_hash_bucket_size;    ngx_uint_t                 variables_hash_max_size;    ngx_uint_t                 variables_hash_bucket_size;    ngx_hash_keys_arrays_t    *variables_keys;/**    * 监听的所有端口,ngx_http_port_t类型,其中包含socket地址信息。    */      ngx_array_t               *ports;    ngx_uint_t                 try_files;       /* unsigned  try_files:1 */    /**      * 所有的phase的数组,其中每个元素是该phase上注册的handler的数组。      */      ngx_http_phase_t           phases[NGX_HTTP_LOG_PHASE + 1];} ngx_http_core_main_conf_t;
这个配置结构一看就知道很重要了,首先来看servers域,它是一个ngx_http_core_module模块的srv_conf结构的数组,听起来很奇葩,不过就是这样的,因为在http命令里面可能会包含几个server命令,知道这个也就不会觉得奇怪了,另外还有一个比较重要的域,那就是ports域,它代表所有需要监听的端口。

嗯,接下来看ngx_http_core_module模块的srv_conf类型的配置:

typedef struct {    /* array of the ngx_http_server_name_t, "server_name" directive */    ngx_array_t                 server_names;  //server的名字数组    /* server ctx */    ngx_http_conf_ctx_t        *ctx;  // 指向包含它的ngx_http_conf_ctx_t结构    ngx_str_t                   server_name;  //名字    size_t                      connection_pool_size;    size_t                      request_pool_size;    size_t                      client_header_buffer_size;    ngx_bufs_t                  large_client_header_buffers;    ngx_msec_t                  client_header_timeout;    ngx_flag_t                  ignore_invalid_headers;    ngx_flag_t                  merge_slashes;    ngx_flag_t                  underscores_in_headers;    unsigned                    listen:1;  //区别当前server是否监听#if (NGX_PCRE)    unsigned                    captures:1;#endif    ngx_http_core_loc_conf_t  **named_locations;  //该srv配置的location配置数组} ngx_http_core_srv_conf_t;
其实这个配置没什么好讲的,许多一看名字就能看的差不多知道什么意思了。接下就是ngx_http_core_module模块的loc_conf了,嗯,这个结构是ngx_http_core_loc_conf_s,嗯,它的定义太长了,以后用到的时候再讲吧。

接下来我们来看一下http命令的一个例子吧,也就不难明白未什么要这么安排了:

http {        include       mime.types;        default_type  application/octet-stream;        sendfile        on;        keepalive_timeout  65;        #gzip  on;            #反向代理配置 ,向内网6台jboss转发        upstream jboss {            server 192.168.162.35:8080 weight=10;          server 192.168.162.11:8080 weight=8;          server 192.168.162.61:8080 weight=2;      }            server {            listen       2011;            server_name  localhost;                location ~ ^/nginx_status/ {                stub_status on;                access_log off;            }                location / {                proxy_pass http://jboss;            }                error_page   500 502 503 504  /50x.html;            location = /50x.html {                root   html;            }            }        }   
一个http命令里面可能对应几个server命令,一个server命令又可能会对应好几个location命令。好吧,所以我们就知道一个http模块的配置信息可能存在三个地方,第一个就是http内,server外,这个用main_conf保存,还有一个是server内,location外,这个用srv_conf结构保存,还有的就是在location里面了,因而就用loc_conf配置结构来保存)

好了,已经写了这么多,居然还只是讲完了配置,嗯,那就下一篇在写真正的初始化过程吧。

原创粉丝点击