当前位置:K88软件开发文章中心网站服务器框架nginx → 文章内容

Nginx 过滤模块的分析

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-23 14:28:57

由 小路依依 创建, 最后一次修改 2016-08-12 过滤模块的分析相关结构体ngx_chain_t 结构非常简单,是一个单向链表: typedef struct ngx_chain_s ngx_chain_t; struct ngx_chain_s { ngx_buf_t *buf; ngx_chain_t *next; };在过滤模块中,所有输出的内容都是通过一条单向链表所组成。这种单向链表的设计,正好应和了 Nginx 流式的输出模式。每次 Nginx 都是读到一部分的内容,就放到链表,然后输出出去。这种设计的好处是简单,非阻塞,但是相应的问题就是跨链表的内容操作非常麻烦,如果需要跨链表,很多时候都只能缓存链表的内容。单链表负载的就是 ngx_buf_t,这个结构体使用非常广泛,先让我们看下该结构体的代码: struct ngx_buf_s { u_char *pos; /* 当前buffer真实内容的起始位置 */ u_char *last; /* 当前buffer真实内容的结束位置 */ off_t file_pos; /* 在文件中真实内容的起始位置 */ off_t file_last; /* 在文件中真实内容的结束位置 */ u_char *start; /* buffer内存的开始分配的位置 */ u_char *end; /* buffer内存的结束分配的位置 */ ngx_buf_tag_t tag; /* buffer属于哪个模块的标志 */ ngx_file_t *file; /* buffer所引用的文件 */ /* 用来引用替换过后的buffer,以便当所有buffer输出以后, * 这个影子buffer可以被释放。 */ ngx_buf_t *shadow; /* the buf's content could be changed */ unsigned temporary:1; /* * the buf's content is in a memory cache or in a read only memory * and must not be changed */ unsigned memory:1; /* the buf's content is mmap()ed and must not be changed */ unsigned mmap:1; unsigned recycled:1; /* 内存可以被输出并回收 */ unsigned in_file:1; /* buffer的内容在文件中 */ /* 马上全部输出buffer的内容, gzip模块里面用得比较多 */ unsigned flush:1; /* 基本上是一段输出链的最后一个buffer带的标志,标示可以输出, * 有些零长度的buffer也可以置该标志 */ unsigned sync:1; /* 所有请求里面最后一块buffer,包含子请求 */ unsigned last_buf:1; /* 当前请求输出链的最后一块buffer */ unsigned last_in_chain:1; /* shadow链里面的最后buffer,可以释放buffer了 */ unsigned last_shadow:1; /* 是否是暂存文件 */ unsigned temp_file:1; /* 统计用,表示使用次数 */ /* STUB */ int num; };一般 buffer 结构体可以表示一块内存,内存的起始和结束地址分别用 start 和 end 表示,pos 和 last 表示实际的内容。如果内容已经处理过了,pos 的位置就可以往后移动。如果读取到新的内容,last 的位置就会往后移动。所以 buffer 可以在多次调用过程中使用。如果 last 等于 end,就说明这块内存已经用完了。如果 pos 等于 last,说明内存已经处理完了。下面是一个简单的示意图,说明 buffer 中指针的用法:响应头过滤函数响应头过滤函数主要的用处就是处理 HTTP 响应的头,可以根据实际情况对于响应头进行修改或者添加删除。响应头过滤函数先于响应体过滤函数,而且只调用一次,所以一般可作过滤模块的初始化工作。响应头过滤函数的入口只有一个: ngx_int_t ngx_http_send_header(ngx_http_request_t *r) { ... return ngx_http_top_header_filter(r); }该函数向客户端发送回复的时候调用,然后按前一节所述的执行顺序。该函数的返回值一般是 NGX_OK,NGX_ERROR 和 NGX_AGAIN,分别表示处理成功,失败和未完成。你可以把 HTTP 响应头的存储方式想象成一个 hash 表,在 Nginx 内部可以很方便地查找和修改各个响应头部,ngx_http_header_filter_module 过滤模块把所有的 HTTP 头组合成一个完整的 buffer,最终 ngx_http_write_filter_module 过滤模块把 buffer 输出。按照前一节过滤模块的顺序,依次讲解如下:filter moduledescriptionngx_http_not_modified_filter_module默认打开,如果请求的 if-modified-since 等于回复的 last-modified 间值,说明回复没有变化,清空所有回复的内容,返回 304。ngx_http_range_body_filter_module默认打开,只是响应体过滤函数,支持 range 功能,如果请求包含range请求,那就只发送range请求的一段内容。ngx_http_copy_filter_module始终打开,只是响应体过滤函数, 主要工作是把文件中内容读到内存中,以便进行处理。ngx_http_headers_filter_module始终打开,可以设置 expire 和 Cache-control 头,可以添加任意名称的头ngx_http_userid_filter_module默认关闭,可以添加统计用的识别用户的 cookie。ngx_http_charset_filter_module默认关闭,可以添加 charset,也可以将内容从一种字符集转换到另外一种字符集,不支持多字节字符集。ngx_http_ssi_filter_module默认关闭,过滤 SSI 请求,可以发起子请求,去获取include进来的文件ngx_http_postpone_filter_module始终打开,用来将子请求和主请求的输出链合并ngx_http_gzip_filter_module默认关闭,支持流式的压缩内容ngx_http_range_header_filter_module默认打开,只是响应头过滤函数,用来解析range头,并产生range响应的头。ngx_http_chunked_filter_module默认打开,对于 HTTP/1.1 和缺少 content-length 的回复自动打开。ngx_http_header_filter_module始终打开,用来将所有 header 组

[1] [2]  下一页


Nginx 过滤模块的分析