Nginx:HTTP框架是如何介入请求
参考资料 <深入理解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框架是如何介入请求的更多相关文章
- Nginx Http框架的理解
Nginx Http框架的理解 HTTP框架是Nginx基础框架的一部分,Nginx的其它底层框架如master-worker进程模型.event模块.mail 模块等. HTTP框架代码主要有2个模 ...
- nginx反向代理实现跨域请求
nginx反向代理实现跨域请求 跨域请求可以通过JSONP实现,缺点是需要修改被请求的服务器端代码进行配合,稍显麻烦通过在自己服务器上配置nginx的反向代理,可以轻松实现跨域请求 思路 示例服务器A ...
- JAVA获取客户端请求的当前网络ip地址(附:Nginx反向代理后获取客户端请求的真实IP)
1. JAVA获取客户端请求的当前网络ip地址: /** * 获取客户端请求的当前网络ip * @param request * @return */ public static String get ...
- Nginx 限制并发连接和并发请求数配置
Nginx限制并发连接和并发请求数配置 by:授客 QQ:1033553122 测试环境 nginx-1.10.0 配置介绍 查看是否内置模块 # pwd /mnt/nginx-1.10.0 ...
- TP框架中ajax post请求时提示404
ajax post请求时提示404错误 TP框架中ajax post请求时提示404 找了半天是 控制器中方法有错误! 下次再遇到去控制器方法中找一步一步找,肯定能找到,我是单词拼错了!
- Django框架 之 跨域请求伪造
Django框架 之 跨域请求伪造 浏览目录 同源策略与Jsonp 同源策略 Jsonp jQuery对JSONP的实现 CORS 简介 两种请求 同源策略与Jsonp 同源策略 同源策略(Same ...
- Android 利用an框架快速实现网络请求(含下载上传文件)
作者:Bgwan链接:https://zhuanlan.zhihu.com/p/22573081来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. an框架的网络框架是完全 ...
- Flask框架(三)—— 请求扩展、中间件、蓝图、session源码分析
Flask框架(三)—— 请求扩展.中间件.蓝图.session源码分析 目录 请求扩展.中间件.蓝图.session源码分析 一.请求扩展 1.before_request 2.after_requ ...
- Flask框架 (四)—— 请求上下文源码分析、g对象、第三方插件(flask_session、flask_script、wtforms)、信号
Flask框架 (四)—— 请求上下文源码分析.g对象.第三方插件(flask_session.flask_script.wtforms).信号 目录 请求上下文源码分析.g对象.第三方插件(flas ...
随机推荐
- request_mem_region 与 ioremap【转】
转自:http://blog.csdn.net/alada007/article/details/7700125 如果从根本上说起的话应该从Intel的处理器芯片与其它的芯片的不同说起,与这两个函数相 ...
- python--traceback模块
#!/usr/bin/env python # -*- coding:utf-8 -*- # author:love_cat # 异常处理在python中已经屡见不鲜了,我们不仅可以处理异常,也可以将 ...
- C/51单片机
1. 串口也可以有多根线的,但是各线之间没有协调同步发送,而是各自是独自发送的.并口是同步发送,同步一次8位同时成功同时失败,类比事务. 2. ASCII码的前32位是通讯预留的编码即使现 ...
- HTML,DIV+CSS,js,JQ,UI-WEB前端设计经验
目前比较全的CSS重设(reset)方法总结 在当今网页设计/开发实践中,使用CSS来为语义化的(X)HTML标记添加样式风格是重要的关键.在设计师们的梦想中都存在着这样的一个完美世界:所有的浏览 ...
- 允许root用户登录ssh
使用普通用户登录Ubuntu系统,打开命令行窗口 更改root用户密码,命令:sudo passwd root 首先输入当前用户的密码 然后输入root账户的密码 确认root用户的密码 编辑ssh的 ...
- (33)C#正则表达式
正则表达式:专门用于字符串处理的语言,用来描述字符串特征的表达式 元字符 . 之间可以出现任意单个字符(除了\n 换行) 例如: a.b 意思是这个表达式必须是三个字符,第一个字符是a,第三个字符 ...
- RQNOJ PID217 / [NOIP1999]拦截导弹【n^2 / LIS】
题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹 ...
- Codeforces #425 Div2 D
#425 Div2 D 题意 给出一个树形图,每次询问给出三个点,从其中选择两个作为起始点,一个终点,求从两个起始点出发(走最短路)到达终点经过的共同的点最多的数量. 分析 这种树上点与点之间距离有关 ...
- EGS5在linux系统下安装过程
转载自52MC论坛 作者:xinruibj 平台:Fedora 13 内核版本为:2.6.33, g77版本为:3.4.6: 用户名为xinrui,下面出现这个文件夹xinrui时,修改为你自己的用户 ...
- 【分享】· 图床&在线分享演示文稿
关于图床 什么是图床? 这并不是一个多么高大上的名词概念!用比较通俗的话来说,当你在撰写新文章时,你需要去插入图片以使得你的文章内容更加直观.易懂,这个时候有以下几种办法: 在博客根目录的 sourc ...