Nginx源码分析—架构设计思想
我任务nginx的源码可以分为三个部分,一个是在ngx_init_cycle之前,这个也算是为了重新启动nginx而准备的代码,比如说在这个时候可以接受外部的信号,也可以保存传递的参数,等等,当然在以后的函数中也考虑了是否正在重启nginx。
至于ngx_init_cycle这个函数,是一个很庞大的函数,在这个函数中可以看到调用了各个模块的钩子函数,这里又设计到了nginx结构体的使用,比如所有的模块都是ngx_module_t这个结构体,但是这个结构体中的ctx变量和commands type这三个变量使得各个module的功能又有所不同。将每一个模块都有所归类
对于一个标准的HTTP请求中,nginx框架试图结束完整的HTTP头部,并在接收到完整的HTPP头部后将请求分发到具体的HTTP模块中处理,最常见的即使根据请求的URI(URI在HTTP请求的头部信息中)和ngin.conf里的location配置项的匹配度来决定如何分发。
HTTP模块间数据流的传递,各个模块之间的写通过工作,配置文件中的Location块决定了匹配某种URI的请求将会由相应的HTTP模块处理,因此,运行时HTTP框架会在接收完毕HTTP请求的头部后,将请求的URI与配置文件中的所有location进行匹配,匹配后再根据Location{}内的配置项选择HTTP模块来调用。
对于ngx_moudle_t结构体中的init_module init_process 函数指针,前者是在初始化所有模块时被调用,后者是在worker进程已经产生时被调用,这两个函数指针之后再ngx_core_event_module模块中实现了这几个调用时和nginx框架相关的,对于一个HTTP模块,NGX_HTTP_MODULE,ngx_module_t中的ctx指向ngx_http_module_t类型的结构体,这个结构体中有8个函数指针,nginx狂a级会在不同的时刻调用这个8个回调来读取重载配置文件。
一个HTTP请求会被许多个配置项控制,实际上这是因为一个HTTP请求可以被许多个HTTP模块同时处理,这样就会有一个先手顺序问题。由于同一个配置项可以从属与许多个server location配置快,那么这个配置项将会针对不同的请求起作用。自己有很大的自由来定义自己的模块如何介入HTTP请求的处理,
可以这么认为,某一个配置项,在不同的层次有不同的作用域,配置项决定了自己感兴趣的HTTP请求。
可以这么理解配置项,配置项是对某一类HTTP请求感兴趣,这个配置项放到某一个配置块内,当某一类HTTP请求到达后进行匹配,根据配置项来判断有哪些模块对自己这个HTTP请求感兴趣,那么系统就进行控制对这个HTTP请求调用这个配置项对应的HTTP模块
对于一个有参数的配置项,在NGINX中定义了14个常用的类型来标识配置项中的参数类型,也有对应的参数来处理这些参数。
http{}块下有一个ngx_http_conf_ctx_t结构,而每一个serve{}块下也有一个ngx_http_conf_ctx_t结构
NGINX源码分析—过滤模块的意义
HTTP框架允许普通的HTTP处理模块介入其中的7个阶段处理请求,但是普通大部分HTTP模块(官方模块或者第三方模块)都只在NGX_HTTP_CONTENT_PHASE阶段处理请求,HTTP模块有两种介入方法,第一种是,任意一个HTTP模块会对所有的用户请求产生作用,第二中方法,只对请求的URI匹配了nginx.conf中某些location表达式下的HTTP模块起作用,大部分模块都使用上述的第二种方法处理请求,这种方法的特点是一种请求仅由一个HTTP模块(在NGX_HTTP_CONTENT_PHASE阶段)处理。如果希望多个HTTP模块共同处理一个请求,则多半是由subrequest功能来完成,即将原始请求分为多个子请求,每个子请求再由一个HTTP模块在NGX_HTTP_CONTENT_PHASE阶段处理。
对于HTTP过滤模块则不同,一个请求可以被任意个HTTP过滤模块处理,因此,普通的HTTP模块更倾向于完成请求的核心功能,如static模块复制静态文件的处理,HTTP过滤模块则处理一些附加的功能,如gzip过滤模块可以把发送给用户的静态文件进行gzip压缩后在发出去,Image_filter这个第三方过滤模块可以将图片类的静态文件制作成缩略图。而且,这些过滤模块的效果是可以根据需要叠加的,比如先由Not_modify过滤模块处理请求中的浏览器缓存信息,再交给range过滤模块处理HTTP
range协议(支持断点续传),然后交由gzip过滤模块进行压缩,一个请求经由各HTTP过滤模块流水线般地依次进行处理了。
在普通HTTP模块处理请求完毕,并调用ngx_http_send_header发送HTTP头部,或者调用ngx_http_output_filter发送HTTP包体时,才会由这两个方法依次调用所有的HTTP过滤模块处理这个请求,因此,HTTP过滤模块仅处理服务器发往客户端的HTTP响应,而不处理客户端发往服务器的HTTP请求
NGINX在进行回应时,分为头部回应和包体回应,那么过滤链表也分为两个部分,对于某一个过滤模块,插入的时候都是插入这个链表的首部,所以,HTTP过滤模块越靠后,在实际执行请求时就越优先执行,以为在初始化HTTP过滤模块式,每一个HTTP过滤模块都是将自己插入到整个单链表的首部。