ngx_http_core_module.c负责处理nginx里面的所有配置
其中的关键还是这个变量:ngx_http_core_module
一个ngx_module_t类型的结构体,这个结构体在前面已经提到过,他遍布ngx的各个Module,包括底层i/o模型的module均是用这个结构体来传递上下文
这里的定义是这样的
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
};
其中重点是ngx_http_core_commands这个成员,它包含了所有ngx主配置文件涉及的关键字已经处理这个关键字的函数
内容太多,先看看涉及location的一段
{ ngx_string("location"),
NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
ngx_http_core_location,
NGX_HTTP_SRV_CONF_OFFSET,
0,
NULL },
大致了解一下这些数据结构,再来看看函数调用栈
前面upstream一节已经介绍,当ngx需要执行反向代理,向后端apache或者tomcat之类发起请求的时候,会调用ngx_http_proxy_handler
ngx_http_proxy_handler是如何被初始化并挂载到处理流程中的?
先看看各个module的初始化
ngx_http_static_handler,ngx_http_proxy_handler,ngx_http_indixe_handler的初始化在各自模块的init函数进行,比如初始化ngx_http_static_handler的是ngx_http_static_init
,这个函数需要在ngx_http.c的 ngx_http_block中初始化。
ngx_modules.c的
ngx_module_t *ngx_modules[] = {
&ngx_core_module,
&ngx_errlog_module,
&ngx_conf_module,
&ngx_events_module,
&ngx_event_core_module,
&ngx_epoll_module,
&ngx_regex_module,
&ngx_http_module,
&ngx_http_core_module,
&ngx_http_log_module,
&ngx_http_upstream_module,
&ngx_http_static_module,
&ngx_http_autoindex_module,
&ngx_http_index_module,
&ngx_http_auth_basic_module,
&ngx_http_access_module,
&ngx_http_limit_conn_module,
&ngx_http_limit_req_module,
&ngx_http_geo_module,
&ngx_http_map_module,
&ngx_http_split_clients_module,
&ngx_http_referer_module,
&ngx_http_rewrite_module,
&ngx_http_proxy_module,
&ngx_http_fastcgi_module,
&ngx_http_uwsgi_module,
&ngx_http_scgi_module,
&ngx_http_memcached_module,
&ngx_http_empty_gif_module,
&ngx_http_browser_module,
&ngx_http_upstream_hash_module,
&ngx_http_upstream_ip_hash_module,
&ngx_http_upstream_least_conn_module,
&ngx_http_upstream_keepalive_module,
&ngx_http_write_filter_module,
&ngx_http_header_filter_module,
&ngx_http_chunked_filter_module,
&ngx_http_range_header_filter_module,
&ngx_http_gzip_filter_module,
&ngx_http_postpone_filter_module,
&ngx_http_ssi_filter_module,
&ngx_http_charset_filter_module,
&ngx_http_userid_filter_module,
&ngx_http_headers_filter_module,
&ngx_http_echo_module,
&ngx_http_copy_filter_module,
&ngx_http_range_body_filter_module,
&ngx_http_not_modified_filter_module,
NULL
};
定义了所有的模块,里面可以看到ngx_http_static_module,
下面的代码正式调用各模块的init
for (m = 0; ngx_modules[m]; m++) {
if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
continue;
}
module = ngx_modules[m]->ctx;
if (module->postconfiguration) {
if (module->postconfiguration(cf) != NGX_OK) {
return NGX_CONF_ERROR;
}
}
}
static module的初始化函数代码如下
static ngx_int_t
ngx_http_static_init(ngx_conf_t *cf)
{
ngx_http_handler_pt *h;
ngx_http_core_main_conf_t *cmcf;
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
*h = ngx_http_static_handler;
return NGX_OK;
}
可以看到在cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers中写入了ngx_http_static_handler的函数指针,以后在处理请求的NGX_HTTP_CONTENT_PHASE阶段,这个函数会被调用
但回头看看proxy module。他并没有直接注册handler。而是在初始化配置文件过程中,ngx_http_proxy_pass函数会处理proxy_pass关键字,这时会在ngx_http_core_loc_conf_s结构中填写ngx_http_proxy_handler函数指针。
调用过程则是这样的:
在HTTP处理流程的NGX_HTTP_FIND_CONFIG_PHASE阶段。ngx_http_core_find_config_phase函数会查找ngx_http_request_t对应的location,然后调用ngx_http_update_location_config
这里,会把刚才注册的ngx_http_proxy_handler传递给ngx_http_request_t下面的content_handler
继续流程,会执行到NGX_HTTP_CONTENT_PHASE这个阶段,对应的处理函数是ngx_http_core_content_phase
这里首先就会判断r是否存在content_handler指针,如果是,则会直接调用ngx_http_finalize_request(r, r->content_handler(r));
首先执行ngx_http_proxy_handler,然后执行ngx_http_finalize_request本身结束当前的流程。