极客专栏《Nginx核心知识100讲》69~71小节,笔记
注意:这个是看专栏视频,敲的哈。这个专栏让我收货蛮大的。
69 | HTTP过滤模块的调用流程
在content阶段会生成返回给用户的响应内容。对用户的响应内容还需要代加工处理。过滤模块正是对响应模块做加工处理。所以,实际上是在Log模块之前,Content阶段之后接入处理。
过滤模块的位置
image.png做缩略图(imag_filter),不能先做gzip。做完压缩之后,缩略图就没法做了。image_filter跟gzip是有严格的顺序的。
有一些过滤模块只对body操作,不需要对header操作。有些模块只对header操作不需要对body操作。
返回响应-加工响应内容
image.png这些http过滤模块,它们的顺序也很重要。就像我们之前提到的在11个阶段的顺序,以及每一个阶段http模块顺序会影响我们的请求处理一样。它也有很重要的影响。这些模块的顺序是怎样的呢?我们看下nginx_module.c中的那个数组。那个数组的所有过滤模块会以这样的顺序(看右半图)写出来。从下往上看。一个请求会首先被下面的http模块处理,再 依次的被上面的过滤模块挨个的处理。在这个顺序中,重点关注四个http模块——copy_filter
、postpone_filter
、header_filter
、write_filter
。
copy_filter:复制包体的内容。如果说我们使用了sendfile指令,copy_filter实际上用了零拷贝技术,也就是,把一个文件的内容不经过用户态的内存(也就是nginx)直接发给用户了。如果我们用了gzip这个模块,gzip必须要放到sendfile之后,因为gzip要对内存中的内容做压缩。所以,当我们打开gzip以后copy_filter就会让sendfile失效,然后把文件中的内容先拷贝到内存中,交给后续的模块进行处理。所以copyfilter是第一个我们需要关注的模块。所以,有一些http的过滤模块呢。它不需要对内存中的内容做处理。它就可以在下面出现(一些第三方的过了模块),其他的呢,就在上面出现。
postpone_filter:用来处理子请求。有些过滤模块会关注子请求的结果。应该在header_filter
、write_filter
之后。
header_filter:用来构造响应的头部。前面的http模块,如果处理了header响应的头部。实际上是由head_filter
来构造,最终发给用户的一个响应的。可能会添加一些像server、nginx的版本号等这样一些内容。
write_filter:虽然它名字叫filter,但其实它最终负责调用操作系统的write、或者send这样的系统调用,来把内存中的内容,真的发给客户端的。
http过滤模块会改变发往用户的响应的,所以它的用法非常的广泛。
留言问题
- preaccess => access => content => header => body
这个流程 像串糖葫芦一样把HTTP流程串起来
作者回复
:-)
70 | 用过滤模块更改响应中的字符串:sub模块
把返回用户响应内容的字符串替换成我们指定的新的字符串。
image.pngsub模块指令
image.pngsub_filter:需要把返回给用户响应中什么样的字符串。匹配上以后,给它换成新的字符串。
sub_filter_last_modified:相当于修改返回给用户的响应。是否还需要显示原先的请求中返回的last_modified。默认是关闭的,也就是不会返回last_modified。
sub_filter_once:只修改一次。匹配上string换上了replacement以后,如果我们开启了filter_once on这次替换就结束了。如果设置成了off了呢?就会扫描完整的body,把所有匹配上的字符串都替换成年了replacement。
sub_filter_types:只针对什么样的响应去替换。我们可以设为*
,也就是对所有的类型的响应都试图去查找。当然这样的效率是比较差的。
一个例子
image.png先把所有都注释。然后访问首页。应该会得到的就是我们nginx默认的欢迎值。
image.png这里有两个超链接,nginx.org 和nginx.com。
image.png接下来替换,内容里的内容。注意:在替换的时候是忽略大小写的。
image.png替换了
image.pnglast_modified没有返回。
image.png image.png看到全部被替换掉了。
image.pnglast_modified也加上了 。
image.png留言问题
1.为什么开启sub_filter_once的时候页面的nginx.org文案没有换成你要替换的文案呢。关掉sub_filter_once的时候页面的文案就改变了。
作者回复
应该是有多个地方都符合替换条件,你只观察到一处了。开启sub_filter_once,对文件从头开始比较,发现匹配替换一处后就停止;关掉后,则替换所有的地方。
2.这个模块不太常用吧
作者回复
相对使用场景更狭窄一些
71 | 用过滤模块在http响应的前后添加内容:addition模块
这个模块可以在原始的,返回给用户的响应中,响应的之前或之后添加一些内容。
image.png通过新增一个子请求,通过这个子请求返回的响应再添加到原始响应的前或后中。
指令
image.pngadd_before_body:body之前添加一些内容,添加的内容呢就是后面我们制定的uri。让nginx去访问这个uri。根据这个子请求返回的响应内容再增加到body之前。
addition_types:是与刚刚介绍的sub那个模块是非常相似的。它也是指定怎样的content-type类型才能够使用这样的指令。因为对于一些二进制等等这样格式,在之前或者之后添加内容是没有意义的。addition_types同样也接受,当我们传入*
对所有的文件类型产生作用。
一个例子
image.png image.png接着把注释取消。可以看到有两个url,before_action
和after_action
。当然我们也可以使用反向代理访问第三方服务。但是这里简单用return指令返回新的不同的字符串。
然后看到在内容前后添加了响应的内容。
image.png留言问题
1.怎么感觉跟装饰器的功能类似,在前或在后增加内容。
作者回复
需求总是相似的:-)
2.nginx中的子请求是怎么实现的?是通过开启一个子进程做的吗?
作者回复
不是开启子进程,就是暂时阻住原始请求的执行,同时产生新的子请求上下文,仍然在所属worker进程内执行,获得响应后再激活原始请求。第6部分有一节课会介绍到。
3.addition 模块 可以用来给Web应用加个copyright?
作者回复
可以,或者用前端框架来做
网友评论