参考资料 <深入理解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模块合作处理请求的。

最新文章

  1. 在 Windows7 上按照 MySQL5.7
  2. JavaScript返回上一级,并重新加载页面
  3. hdu 5000 dp **
  4. PowerDesigner的使用一
  5. 【接口测试】Jenkins+Ant+Jmeter搭建持续集成的接口测试平台
  6. javascript散列表实现
  7. JSP-05- JSP总结
  8. yii criteria select column as 与 时间段查询
  9. spring XML格式
  10. CodeForces 158B Taxi(贪心)
  11. (中等) HDU 4069 Squiggly Sudoku , DLX+精确覆盖。
  12. Linux 下如何安装 JDK ,以 Ubuntu 为例。
  13. 限制input[type=number]的输入位数策略整理
  14. Charles 连接手机抓包出现Unknown,一直无法抓包的问题解决
  15. 每日分享!~ JavaScript(js数组如何在指定的位置插入一个元素)
  16. H5 基于Web Storage 的客户端留言板
  17. Groovy 设计模式 -- 保镖模式
  18. flask框架----整合Flask中的目录结构
  19. IO密集型 计算密集型
  20. Windows下war包部署到Linux下Tomcat出现的问题

热门文章

  1. [leetcode]Convert Sorted Array to Binary Search Tre
  2. 基于V4L2的视频驱动开发【转】
  3. shell编程学习笔记【原创】
  4. kvm虚拟机最佳实践系列3-kvm克隆和静态迁移
  5. 使用jquery实现省市二级列表
  6. MVC 视图与控制器传值的几种方法
  7. AC日记——玻璃切割 51nod 1562
  8. (2)WPF XAML
  9. 牛客小白月赛3 F 异或【区间交集】
  10. UVALive(LA) 4487 Exclusive-OR(带权并查集)