一、模块简介

过滤(filter)模块是过滤响应头和内容的模块,可以对回复的头和内容进行处理。它的处理时间在获取回复内容之后,向用户发送响应之前。它的处理过程分为两个阶段,过滤HTTP回复和头部和主体,在这两个阶段可以分别对头部和主体进行修改。下面函数就是分别对头部和主体进行过滤的函数,所有模块的响应内容要返回给客户端,都必须调用这两个接口:

ngx_http_top_header_filter(r);

ngx_http_top_body_filter(r, in);

二、执行顺序

过滤模块的调用是有顺序的,这在编译的时候就决定了,控制编译的脚本位于auto/modules中,当编译完Nginx之后,可以在objs目录下看到一个ngx_modules.c的文件,打开这个文件能看到如下数据结构:

ngx_module_t *ngx_modules[] = {...&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_copy_filter_module,&ngx_http_range_body_filter_module,&ngx_http_not_modified_filter_module,NULL
};

从write_filter到not_modified_filter,模块的执行顺序是反向的,即最早执行的是not_modified_filter,然后各个模块依次执行。所有第三方模块只能加入到copy_filter和headers_filter模块之间执行。每个filter模块的处理函数赋值给全局变量ngx_http_top_header_filter,而前一个filter模块的处理函数赋值给局部变量ngx_http_next_header_filter,响应头和响应体过滤函数的执行顺序如下图:

三、模块编译

Nginx可以很方便地加入第三方过滤模块。在过滤模块的目录里加入config文件,内容如下:

typedef struct ngx_chain_s ngx_chain_t;
struct ngx_chain_s {ngx_buf_t *buf;ngx_chain_t *next;
};

一般buffer结构体可以表示一种内存,内存的起始和结束地址分别用start和end表示,pos和last表示实际的内容。如果内容已经处理过了,pos的位置就可以往后移动。如果读取到新的内容,last的位置就会往后移动。所有buffer可以在多次调用过程中使用。如果last等于end,就说明这块内存已经用完了。如果pos等于last,说明内存已经处理完了,下面是一个简单的示意图,说明buffer中指针的用法:

五、过滤函数

1、响应头过滤函数

响应头过滤函数的主要用处是处理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,分别表示处理成功、失败和未完成。

ngx_http_header_filter_module过滤模块把所有的HTTP头组合成一个完成的buffer,最终由ngx_http_write_filter_module过滤模块把所有的HTTP头组合成一个完成的buffer,最终由ngx_http_write_filter_module过滤模块把buffer输出。

2、响应体过滤函数

响应体过滤模块是过滤响应主题的函数。对于每个请求,函数ngx_http_top_body_filter可能会被执行多次,它的入口函数如下:

ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
{ngx_int_t rc;ngx_connection_t *c;c = r->connection;rc = ngx_http_top_body_filter(r, in);if (rc == NGX_ERROR) {/* NGX_ERROR may be returned by any filter */c->error = 1;}return rc;
}

对于整个请求的处理阶段来说,ngx_http_output_filter的作用就是把响应内存过滤,然后发给客户端,具体模块的响应体过滤函数的格式会类似如下:

static int ngx_http_example_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{...return ngx_http_next_body_filter(r, in);
}

该函数的返回值一般是NGX_OK、NGX_ERROR和NGX_AGAIN,分别表示处理成功、失败和未完成。

响应的主体内容就存于单链表in,链表一般不会太长,有时in参数可能为NULL。in中存有buf结构体中,对于静态文件,这个buf大小默认是32K;对于反向代理的应用,这个buf可能是4K或者8K。为了保持内存的低消耗,Nginx一般不会分配过大的内存,处理的原则是收到一定的数据,就发送出去。

在响应体过滤模块中,尤其要注意的是buf的标志位,具体可以参看图2.如果buf中包含last标志,说明是最后一块buf,可以直接输出并结束请求了。如果有flush标志,说明这块buf需要马上输出,不能缓存。如果整块buffer经过处理完以后,没有数据了,你可以把buffer的sync标志置上,表示只是同步的用处。当所有的过滤模块都处理完毕时,在最后的write_filter模块中,Nginx会将in输出链拷贝到r->out输出链的末尾,然后调用sendfile或者writev接口输出。由于Nginx是非阻塞的socket接口,写操作并不一定会成功,可能会有部分数据还残存在r->out。在下次的调用中,Nginx会继续尝试发送,直至成功。

六、子请求

Nginx过滤模块一大特色就是可以发出子请求,即在过滤响应内容的时候,你可以发送新的请求,Nginx会根据你调用的先后顺序,将多个回复的内容拼接成正常的响应主体。一个简单的例子可以参考addtion模块。当Nginx发出子请求时,就会调用ngx_http_subrequest函数,将子请求插入福请求的r->postponed链表中。子请求会在主请求执行完毕时获得依次调用。子请求同样会有一个请求所有的生存期和处理过程,也会进入过滤模块流程。

关键点是在postpone_filter模块中,它会拼接主请求和子请求的响应内容。r->postponed按次序保存有父请求和子请求,它是一个链表,如果前面一个请求未完成,那么后一个请求内容就不会输出。当前一个请求完成时并输出时,后一个请求才可输出,当所有的子请求都完成时,所有的响应内容也就输出完毕了。

Nginx深入详解之过滤模块相关推荐

  1. Nginx配置详解/代理服务的配置说明

    Nginx配置详解 序言 Nginx是lgor Sysoev为俄罗斯访问量第二的rambler.ru站点设计开发的.从2004年发布至今,凭借开源的力量,已经接近成熟与完善. Nginx功能丰富,可作 ...

  2. Nginx 服务详解

    文章目录 前言 1. Nginx 概述 1.1 nginx 特点 1.2 nginx 与 apache 的差异 2. Nginx 编译安装与服务控制 2.1 编译安装过程 2.2 nginx 服务控制 ...

  3. Nginx 架构详解

    Nginx 架构详解 nginx的下篇将会更加深入的介绍nginx的实现原理.上一章,我们了解到了如何设计一个高性能服务器,那这一章将会开始讲解,nginx是如何一步一步实现高性能服务器的. Ngin ...

  4. nginx配置详解1

    Nginx 配置文件详解 user nginx ; #用户 worker_processes 8; #工作进程,根据硬件调整,大于等于cpu核数 error_log logs/nginx_error. ...

  5. Nginx rewrite 详解

    Nginx rewrite 详解 本篇主要介绍 nginx 的 rewrite 重定向这个功能进行 详解介绍, 以及介绍它的使用场景 1. rewrite 基本介绍 rewrite是实现URL重写的关 ...

  6. 配置nginx方向代理,实现URL隐形转发 (附带nginx配置文件详解)

    配置nginx方向代理,实现URL隐形转发 (附带nginx配置文件详解) 免费领取满减阿里云红包 项目名称:[域名解析–隐形URL转发]–centos 7.3 环境: 阿里云服务器之上有多个tomc ...

  7. 学完Nginx/OpenResty详解,反向代理与负载均衡配置,能涨薪多少

    反向代理与负载均衡配置 接下来介绍Nginx的重要功能:反向代理+负载均衡.单体Nginx的性能虽然不错,但也是有瓶颈的.打个比方:用户请求发起一个请求,网站显示的图片量比较大,如果这个时候有大量用户 ...

  8. 本文来深入学习Nginx/OpenResty详解,Nginx到底是个什么鬼

    Nginx/OpenResty详解 Nginx(或OpenResty)在生产场景中使用的广泛程度已经到了令人咂舌的地步.无论其实际的市场占用率如何,以笔者这些年所经历的项目来看,其使用率为100%. ...

  9. nginx学习简介-安装-启动-命令-nginx配置文件详解

    nginx是什么:nginx是一个高性能的HTTP和反向代理web服务器.同时也提供了IMAP/POP3/SMTP服务. nginx特点:开源.占内存少.轻量级.高性能(有报告表面nginx能支持高达 ...

最新文章

  1. 如何解决JavaScript中的根查找
  2. C++ const与define
  3. 火狐浏览器缓存登录名、密码解决方法
  4. (转)在Eclipse中用TODO标签管理任务(Task)
  5. 绿盟漏洞扫描_主机安全漏洞解决方案
  6. python @修饰符_数据结构与算法之8——抽象数据类型与python类
  7. ×××S 2012 高级图表类型 -- 小面积扇形处理
  8. javaweb基础(36)_jdbc进行批处理
  9. 开源APP源代码、游戏源代码
  10. 关于编译ns3的myfirst.cc问题
  11. LaTex 插入超链接
  12. 靶机-droopyCTF Walkthrough
  13. 【EE】案例分享-如何设计继电器电路?
  14. 苹果Mac系统虚拟打印机CAD输出PDF文档软件—pdfwriter
  15. 完整的大数据知识体系,大数据学习路线图
  16. 用结构体指针访问结构体中的结构体指针(结构体指针的嵌套)
  17. 前端做CA认证碰到的坑
  18. 来做做这 48 道 TypeScript 练习题
  19. [分享]linux架设BT Tracker服务器小记
  20. adams matlab 联仿 5DOF机械臂 建模以及联合仿真

热门文章

  1. 多线程编程--异步转同步之CountDownLatch
  2. JAVA内存存储数据的位置
  3. Python里面对于嵌套列表的查询
  4. ensp安装包_教你如何安装华为模拟器Ensp,另分享全套安装包
  5. nginx php fpm 连接数,哪个php5-fpm设置为高并发连接数nginx
  6. ByteBuffer 类
  7. linux环境没有bzip2,Linux系统中安装使用Bzip2来压缩文件的方法讲解
  8. oracle set markup,oracle sql*plus set spool介绍(二)
  9. php的通用变量,认识并使用PHP的全局变量
  10. PHP域名查墙代码,怎么查看域名是否被墙检测(教你一招域名被墙解决办法)