美文网首页Api设计Nginx高端成长之路微服务架构和实践
【充电】《Nginx核心知识100讲》HTTP过滤模块

【充电】《Nginx核心知识100讲》HTTP过滤模块

作者: 言十年 | 来源:发表于2019-01-12 00:22 被阅读4次

    极客专栏《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_filterpostpone_filterheader_filterwrite_filter

    copy_filter:复制包体的内容。如果说我们使用了sendfile指令,copy_filter实际上用了零拷贝技术,也就是,把一个文件的内容不经过用户态的内存(也就是nginx)直接发给用户了。如果我们用了gzip这个模块,gzip必须要放到sendfile之后,因为gzip要对内存中的内容做压缩。所以,当我们打开gzip以后copy_filter就会让sendfile失效,然后把文件中的内容先拷贝到内存中,交给后续的模块进行处理。所以copyfilter是第一个我们需要关注的模块。所以,有一些http的过滤模块呢。它不需要对内存中的内容做处理。它就可以在下面出现(一些第三方的过了模块),其他的呢,就在上面出现。

    postpone_filter:用来处理子请求。有些过滤模块会关注子请求的结果。应该在header_filterwrite_filter之后。

    header_filter:用来构造响应的头部。前面的http模块,如果处理了header响应的头部。实际上是由head_filter来构造,最终发给用户的一个响应的。可能会添加一些像server、nginx的版本号等这样一些内容。

    write_filter:虽然它名字叫filter,但其实它最终负责调用操作系统的write、或者send这样的系统调用,来把内存中的内容,真的发给客户端的。

    http过滤模块会改变发往用户的响应的,所以它的用法非常的广泛。

    留言问题

    1. preaccess => access => content => header => body
      这个流程 像串糖葫芦一样把HTTP流程串起来

     作者回复
    :-)

    70 | 用过滤模块更改响应中的字符串:sub模块

    把返回用户响应内容的字符串替换成我们指定的新的字符串。

    image.png

    sub模块指令

    image.png

    sub_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.png

    last_modified没有返回。

    image.png image.png

    看到全部被替换掉了。

    image.png

    last_modified也加上了 。

    image.png

    留言问题

    1.为什么开启sub_filter_once的时候页面的nginx.org文案没有换成你要替换的文案呢。关掉sub_filter_once的时候页面的文案就改变了。

     作者回复
    应该是有多个地方都符合替换条件,你只观察到一处了。开启sub_filter_once,对文件从头开始比较,发现匹配替换一处后就停止;关掉后,则替换所有的地方。

    2.这个模块不太常用吧

     作者回复
    相对使用场景更狭窄一些

    71 | 用过滤模块在http响应的前后添加内容:addition模块

    这个模块可以在原始的,返回给用户的响应中,响应的之前或之后添加一些内容。

    image.png

    通过新增一个子请求,通过这个子请求返回的响应再添加到原始响应的前或后中。

    指令

    image.png

    add_before_body:body之前添加一些内容,添加的内容呢就是后面我们制定的uri。让nginx去访问这个uri。根据这个子请求返回的响应内容再增加到body之前。

    addition_types:是与刚刚介绍的sub那个模块是非常相似的。它也是指定怎样的content-type类型才能够使用这样的指令。因为对于一些二进制等等这样格式,在之前或者之后添加内容是没有意义的。addition_types同样也接受,当我们传入*对所有的文件类型产生作用。

    一个例子

    image.png image.png

    接着把注释取消。可以看到有两个url,before_actionafter_action。当然我们也可以使用反向代理访问第三方服务。但是这里简单用return指令返回新的不同的字符串。

    image.png

    然后看到在内容前后添加了响应的内容。

    image.png

    留言问题

    1.怎么感觉跟装饰器的功能类似,在前或在后增加内容。

     作者回复
    需求总是相似的:-)

    2.nginx中的子请求是怎么实现的?是通过开启一个子进程做的吗?

     作者回复
    不是开启子进程,就是暂时阻住原始请求的执行,同时产生新的子请求上下文,仍然在所属worker进程内执行,获得响应后再激活原始请求。第6部分有一节课会介绍到。

    3.addition 模块 可以用来给Web应用加个copyright?

     作者回复
    可以,或者用前端框架来做

    相关文章

      网友评论

        本文标题:【充电】《Nginx核心知识100讲》HTTP过滤模块

        本文链接:https://www.haomeiwen.com/subject/uyvfdqtx.html