Nginx 是如何处理 HTTP 头部的?
Nginx 处理 HTTP 头部的过程
Nginx 在处理 HTTP 请求之前,首先需要 Nginx 的框架先和客户端建立好连接,然后接收用户发来的 HTTP 的请求行,比如方法、URL 等,然后接收所有的 Header,根据这些 Header 信息,才能决定由哪些 HTTP 模块处理请求。下面这张图,解释了 Nginx 在处理 HTTP 请求之前,所经历的一系列流程,强烈建议收藏保存。下面针对每个部分单独讲解一下。

接收请求事件模块

首先是三次握手,当客户端发来 ACK 之后,由操作系统内核回一个 SYN+ACK,紧接着客户端 ACK 之后,连接建立成功。同时可能有很多 worker 进程都在监听 80 或 443 端口,由操作系统的负载均衡算法,选取一个 worker 进程来处理,这个 worker 进程会通过 epoll_wait 方法,返回一个建立连接的句柄。拿到了监听的句柄之后,这实际上是一个读事件(因为是从操作系统中读取到了一个请求),调用 accept 方法,分配连接内存池。
内存池主要分为连接内存池和请求内存池。
连接内存池大小的配置是 connection_pool_size,到了这一步之后,Nginx 会为已经建立的连接分配一个 512 字节大小的连接内存池。分配完内存池,建立好连接之后,HTTP 模块会从事件模块手里接入请求处理的过程,HTTP 模块在启动时,会调用 ngx_http_init_connection 方法来设置回调方法,这个时候会把新建立连接的读事件通过 epoll_ctl 函数添加到 epoll 中,然后加一个超时定时器 client_header_timeout: 60s,这个定时器的作用是,如果超过 60s 还没有接收到客户端发来的请求,那么就会断开连接。这一部分走完之后,Nginx 的事件模块可能就会切换到其他的句柄去处理了。

当用户真的把请求发来之后,操作系统会回复一个 ACK,同时事件模块的 epoll_wait 也拿到了这个请求,这个时候会调用设置的回调方法 ngx_http_wait_request_handler,将接收到的用户请求读到用户态中,而读取到用户态中需要操作系统分配内存,那么这段内存分配多大?从哪里分配呢?
这段内存是从连接内存池分配的,初始虽然分配了 512 字节,但是内存池可以扩展,由 client_header_buffer_size: 1k 分配 1k 内存,内存池并不是越大越好,因为用户即使发送了 1 个字节,也会分配出 1k 的内存出来。当 URL 超过 1k 后,应该怎么办呢?
接收请求 HTTP 模块

处理请求和处理连接是不一样的,处理请求只需要放到 Nginx 内存中就行了,但是处理请求还需要做大量的上下文分析,所以要分配一个请求内存池 request_pool_size: 4k。分配完以后,状态机开始解析请求行,如果这时候发现 URL 大于 4k,那么就会再分配一个大内存,也就是 large_client_header_buffers: 4 8k,这个配置的意思是说,最多分配 4 个 8k,它并不是一次性分配 32k,而是先分配 8k 然后再去解析请求行,如果依然大于 8k,那么就会再分配 8k 的内存。
Nginx 有很多变量,这些变量都是指针,其中可以用来标识 URI,标识完成之后,就开始处理 header。状态机解析 header 的时候,如果发现内存不够,也就是假如 URL 已经用掉了 large_client_header_buffers: 4 8k 中的 2 个 8k,这时候最多也只能分配 8k,请求行和 header 是公用 4 个 8k的。
分配完大内存之后,就开始标识 header,确定哪一个 server 块去处理请求,然后移除超时定时器,接下来,就开始核心的 11 个阶段 HTTP 请求处理请求。
这里需要注意以下几个地方:
- 连接内存池:初始大小 512 字节
- client_header_buffer_size: 1k从连接内存池中分配
- large_client_header_buffers: 4 8k也是从连接内存池中分配
 
- 请求内存池:request_pool_size: 4k
公众号「原少子杨」回复 Nginx 领取知识图谱

Nginx 是如何处理 HTTP 头部的?的更多相关文章
- nginx 是如何处理过期事件的?
		目录 什么是过期事件 nginx 是如何处理过期事件的? 参考资料 什么是过期事件 对于不需要加入到 post 队列 延后处理的事件,nginx 的事件都是通过 ngx_epoll_process_e ... 
- nginx 获取自定义header头部信息
		为了排查线上的bug,需要在nginx的日志中,打印客户端上传上来的header头部信息,同时头部信息是自定义的.在尝试多重方案后,找到解决方法: log_format dm '"$remo ... 
- nginx是如何处理一个请求的(包含https配置)
		配置https首先要有ssl证书,这个证书目前阿里有免费的,但如果自己做实验,也是可以自签证书,只不过不受信 openssl genrsa -des3 -out server.key 1024 ... 
- Nginx是如何处理Request的?
		nginx是如何匹配过来的请求,然后做处理的呢?这个匹配的过程可以分为两步: 1.选择server 2.选择location 选择server 仅仅匹配server name 加入Nginx的配 ... 
- Nginx是如何处理一个请求
		首先,nginx在启动时,会解析配置文件,得到需要监听的端口与ip地址,然后在nginx的master进程里面,先初始化好这个监控的socket(创建socket,设置addrreuse等选项,绑定到 ... 
- Nginx源码结构及如何处理请求
		一.源码结构 1:下载安装包后,解压,可以看到目录结构,其中src目录下放的是源码 2:src源码目录下,可以看到这几个目录 mail:mail目录中存放了实现Nginx服务器 ... 
- nginx平台初探(100%)
		http://tengine.taobao.org/book/chapter_02.html 初探nginx架构(100%)¶ 众所周知,nginx性能高,而nginx的高性能与其架构是分不开的.那么 ... 
- nginx -- nginx平台初探(100%)
		初探nginx架构(100%) 众所周知,nginx性能高,而nginx的高性能与其架构是分不开的.那么nginx究竟是怎么样的呢?这一节我们先来初识一下nginx框架吧. nginx在启动后,在un ... 
- Nginx的虚拟服务器域名配置
		虚拟服务器名(server name)是通过指令server_name来指定的.在< Nginx是如何处理Request的?>一节中,我们讲到nginx分两步来匹配过来的Request请求 ... 
随机推荐
- MySQL数据备份之逻辑备份工具mysqldump
			#前言:我们知道对数据进行备份很重要,出现非正常操作可以进行对数据进行恢复,下面我们就来使用一下mysql数据库自带的一个逻辑备份工具mysqldump 1.简单概述 #mysqldump:mysql ... 
- 用python实现LBP特征点计算
			import cv2 import numpy as np def olbp(src): dst = np.zeros(src.shape,dtype=src.dtype) for i in rang ... 
- nuxt.js如何实现同级目录下建多个动态路由,并将链接设置.html后缀
			nuxt.js中如果在同级目录中建两个_xxxx.vue的动态路由文件,那么页面跳转始终是跳的一个页面,如何解决这个问题呢?下面举个栗子: 第一步:新建两个页面文件 第二步:在nuxt.config. ... 
- MySQL 统计行数的 count
			MySQL count() 函数我们并不陌生,用来统计每张表的函数.但如果你的表越来越大,并且是 InnoDB 引擎的话,会发现计算的速度会越来越慢.在这篇文章里,会先介绍 count() 实现的原理 ... 
- Docker 技术系列之安装Docker Desktop for Mac
			终于要进入到Docker技术系列了,感谢大家的持续关注. 为什么要选择Docker?因为Docker 轻巧快速,提供了可行.经济.高效的替代方案.举个例子,安装Nginx,Mysql,Redis等常用 ... 
- iOS开发技术 - 二维码扫描、生成
			QRecLevel:QR_ECLEVEL_H // 二维码容错率,最高为30%(即QR_ECLEVEL_H),即LOGO有大 ... 
- C# 通过反射访问类库DLL的路径打开窗体功能
			//通过访问目录下的DLL Assembly ass = Assembly.LoadFile(Application.StartupPath + "\\Design.dll"); ... 
- 单片机的 HexToStr  HexToBcd   BcdToStr   几个转换函数
			今天写单片机一个程序 要检查一些数据,想发到串口调试的软件上在电脑上查看 有些转换函数 想网上找一个 看看都是很多的垃圾文章 很多的程序都不能用,那些发文章的人也不用心 所以我还是自己动手写一下吧 写 ... 
- python浅学【网络服务中间件】之Memcached
			一.缓存的由来: 提升性能 绝大多数情况下,select 是出现性能问题最大的地方.一方面,select 会有很多像 join.group.order.like 等这样丰富的语义,而这些语义是非常耗性 ... 
- Javascript之网页版待办事项
			本文使用原生JS实现站点 http://www.todolist.cn/ 的基本功能. 其中页面的HTML布局和CSS样式取用原站,JS部分为自己编写. 效果图 完整代码 HTML.JS部分 < ... 
