参考资料 <深入理解Nginx>(陶辉)

Nginx事件模块博客地址:http://www.cnblogs.com/runnyu/p/4914698.html

Nginx是一个事件驱动构架的Web服务器,在上次的博客中我们可以看到Nginx是如何驱动事件的处理的。

本次将介绍HTTP框架是如何介入跟处理HTTP网络事件的。因为书上的思路已经足够清晰而且内容比较独立,因此本次基本上就把本章的重点记录一下。

HTTP框架存在的目的

1.Nginx事件框架主要是针对传输层的TCP的,作为Web服务器HTTP模块需要处理的则是HTTP,HTTP框架必须要针对基于TCP的事件框架解决好HTTP的网络传输、解析、组装等问题。

2.虽然事件驱动构架在性能上是不错的,但是HTTP模块的业务通常较复杂,HTTP框架的存在则可以让我们屏蔽事件驱动架构,尽量只关注业务,提供开发效率。

新连接建立时的行为

在上次博客的最后可以看到,在ngx_event_accept方法建立连接的最后一步,将会调用ngx_listening_t监听结构体的handler方法。这时候HTTP框架就开始介入请求了。

HTTP框架在初始化时就会将每个监听ngx_listening_t结构体的handler方法设为ngx_http_init_connection方法,该方法执行流程如下图:

其中定时器中的超时时间是nginx.conf配置文件中指定的client_header_timeout,后面的超时时间设定也是这个值。

第一次可读事件的处理

当TCP连接上第一次出现可读事件时,将会调用ngx_http_init_request方法初始化这个HTTP请求

该方法主要做了3件事情:

1.对请求构造ngx_http_request_t结构体并初始化部分参数;

2.修改读事件的回调方法为ngx_http_process_request_line

3.调用上面的回调方法解析HTTP请求行

6.读事件被触发,这是需要在用户态的进程空间分配内存,用来把内核缓冲区上的TCP流复制到用户态的内存中。

这一步将在ngx_connection_t的内存池中分配一块内存,内存块的大小与nginx.conf文件中的client_header_buffer_size配置项参数一致。

ngx_connection_t结构体的buffer指针以及ngx_http_request_t结构体的header_in指针共同指向这块内存缓冲区。

接收HTTP请求行

在初始化请求之后,将调用ngx_http_process_request_line方法接收HTTP请求行。

因为请求行的长度是不定的,这意味着在读事件被触发时,内核套接字缓冲区的大小未必足够接收到全部的HTTP请求行。

因此调用一次ngx_http_process_request_line方法不一定能够接收完完整的HTTP请求行,该方法会被多次调度。下图展示了该方法的流程

该方法会调用recv方法把Linux内核套接字缓冲区中的TCP流复制到header_in缓冲区中。

header_in的类型是ngx_buf_t,它的pos成员和last成员指向的地址之间的内存就是收到的未解析的字符流。

4.在本次没有接收到TCP流的时候,告诉事件驱动程序继续检测这个读事件,然后该方法就结束。在该读事件准备好的时候,该方法将被再次调度。

5.在接收到TCP流后,用状态机(ngx_http_parse_request_line方法)解析已经接收到的TCP字符流,确认其是否构成完整的HTTP请求行。

7.如果ngx_http_parse_request_line方法返回NGX_OK,表示已经成功地接收到完整的请求行。这一步将把请求行的的信息设置到ngx_http_request_t结构体的相应成员中

(request_line、uri、method_name、http_protocol、args等)。

11.接收完HTTP请求行后,把读事件的回调方法更改为ngx_http_request_headers准备接收HTTP头部。

接收HTTP头部

跟HTTP请求行一样,HTTP头部也属于可变长度的字符串,它与HTTP请求行和包体间都是通过换行符来区分的。

下图展示了HTTP框架使用ngx_http_process_request_headers方法接收、解析HTTP头部的流程

6.调用ngx_http_parse_header_line方法解析缓冲区的字符流。这个方法有3个返回值:

返回NGX_OK时,表示解析出一行HTTP头部;返回NGX_HTTP_PARSE_HEADER_DONE时,表示已经解析出了完整的HTTP头部;

返回NGX_AGAIN时,表示还需要接收到更多的字符流才能继续解析;除此之外的错误情况,将发送400错误给客户端。

7.解析出的HTTP头部信息设置到ngx_http_request_t结构体headers_in成员的headers链表中。

9.当ngx_http_parse_header_line方法返回NGX_HTTP_PARSE_HEADER_DONE时,将会根据HTTP头部中的host字段情况,

调用ngx_http_find_virtual_server方法找到对应的虚拟主机配置块。ngx_http_request_t结构体里的srv_conf、loc_conf成员被重新设置,以指向正确的虚拟主机。

在接收到完整的HTTP头部后,已经有足够的必要信息开始在业务上处理HTTP请求了。下一节将说明HTTP框架是如何召集负责具体功能的各HTTP模块合作处理请求的。

Nginx:HTTP框架是如何介入请求的更多相关文章

  1. Nginx Http框架的理解

    Nginx Http框架的理解 HTTP框架是Nginx基础框架的一部分,Nginx的其它底层框架如master-worker进程模型.event模块.mail 模块等. HTTP框架代码主要有2个模 ...

  2. nginx反向代理实现跨域请求

    nginx反向代理实现跨域请求 跨域请求可以通过JSONP实现,缺点是需要修改被请求的服务器端代码进行配合,稍显麻烦通过在自己服务器上配置nginx的反向代理,可以轻松实现跨域请求 思路 示例服务器A ...

  3. JAVA获取客户端请求的当前网络ip地址(附:Nginx反向代理后获取客户端请求的真实IP)

    1. JAVA获取客户端请求的当前网络ip地址: /** * 获取客户端请求的当前网络ip * @param request * @return */ public static String get ...

  4. Nginx 限制并发连接和并发请求数配置

    Nginx限制并发连接和并发请求数配置   by:授客  QQ:1033553122   测试环境 nginx-1.10.0 配置介绍 查看是否内置模块 # pwd /mnt/nginx-1.10.0 ...

  5. TP框架中ajax post请求时提示404

    ajax post请求时提示404错误 TP框架中ajax post请求时提示404 找了半天是 控制器中方法有错误! 下次再遇到去控制器方法中找一步一步找,肯定能找到,我是单词拼错了!

  6. Django框架 之 跨域请求伪造

    Django框架 之 跨域请求伪造 浏览目录 同源策略与Jsonp 同源策略 Jsonp jQuery对JSONP的实现 CORS 简介 两种请求 同源策略与Jsonp 同源策略 同源策略(Same ...

  7. Android 利用an框架快速实现网络请求(含下载上传文件)

    作者:Bgwan链接:https://zhuanlan.zhihu.com/p/22573081来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. an框架的网络框架是完全 ...

  8. Flask框架(三)—— 请求扩展、中间件、蓝图、session源码分析

    Flask框架(三)—— 请求扩展.中间件.蓝图.session源码分析 目录 请求扩展.中间件.蓝图.session源码分析 一.请求扩展 1.before_request 2.after_requ ...

  9. Flask框架 (四)—— 请求上下文源码分析、g对象、第三方插件(flask_session、flask_script、wtforms)、信号

    Flask框架 (四)—— 请求上下文源码分析.g对象.第三方插件(flask_session.flask_script.wtforms).信号 目录 请求上下文源码分析.g对象.第三方插件(flas ...

随机推荐

  1. mysql-\g和\G的作用

    \g 的作用是分号和在sql语句中写’;’是等效的 \G 的作用是将查到的结构旋转90度变成纵向(可以将一个很长的行转为好看的格式) 这两个只能在DOS窗口使用,可视化工具中不能使用. 例如:

  2. ping(NOIP模拟赛Round 4)第一次程序Rank 1!撒花庆祝!~\(≧▽≦)/~

    题目: 恩,就是裸的字符串处理啦. 连标程都打的是暴力(随机数据太水啦!吐槽.) 本来O(n^2q)TLE好吧.. 然后我发明了一种神奇的算法,随机数据跑的很快!,当然最坏复杂度跟标程一样啦. 不过期 ...

  3. RUNAS UAC

    cookielib pip install wmi _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE', 0, _winreg.KEY_ALL ...

  4. UVA 104 Arbitrage

    动态规划类似FLOYD dp[i][j][k] 表示第i个点经过K次到达j点能获得的最大利润 #include <map> #include <set> #include &l ...

  5. Mac下Lua环境搭建

    lua源文件下载安装 到官网安装了lua包,我安装的是 lua-5.3.1 解压之后,命令行cd进入到src目录下,输入make macosx 完成后cd ..到上一层目录, 输入sudo make ...

  6. 处理下最近的file_id小写问题

    update t_resource_info set FILE_ID = UPPER(FILE_ID);update t_resource_my_info set FILE_ID = UPPER(FI ...

  7. STL+Floyd【p1690】贪婪的Copy

    Description Copy从卢牛那里听说在一片叫yz的神的领域埋藏着不少宝藏,于是Copy来到了这个被划分为个区域的神地.卢牛告诉了Copy这里共有个宝藏,分别放在第Pi个(1<=Pi&l ...

  8. HDU 4251 The Famous ICPC Team Again(划分树)

    The Famous ICPC Team Again Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...

  9. centos更改文件所属用户和用户组

    使用命令为chown和chgrp 更改文件夹或者文件的所属用户 chown -R username dirname chown username filename 更改文件夹或者文件的所属用户组 ch ...

  10. webpack2.x基础属性讲解

    webpack作为构建工具平时作为前端作为优化.模块编程.和分片打包的重要组成部分,大家可能并不陌生,如果没有时刻的去关注文档,那么大家可能不太清楚webpack已经默默然的升级到2.x了,对比1.x ...