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请求 ...
随机推荐
- 置顶,博客中所有源码 github
所有项目源代码,开源地址. 作者 github 主页 https://github.com/nejidev 目前开源项目有: 1, linux tea5767 at24c08 mmap 实现fm 收音 ...
- 项目测试中发现产品bug怎么办
我所在的产品线,并非公司最大最强的产品 甚至为了推广我们这个产品,一般会拿给客户先免费试用 而在试用之前,是要经过一番通测的,测得很急,测得很快 所以产品bug非常多 那么在测试项目的时候,自然会发现 ...
- 用libvlc 抓取解码后的帧数据
vlc是一套优秀的开源媒体库,其特点是提供了完整的流媒体框架, 用它可以非常方便的实现抓取解码帧的功能. 与此功能有关的关键API为 libvlc_video_set_callbacks /*设置回调 ...
- Docker极简部署Kafka+Zookeeper+ElasticStack
之前写ELK部分时有朋友问有没有能一键部署的Kafka+ELK,写本文主要是填这个坑,基本上配置已经集中在一两个文件中了,理论上此配置支持ElasticStack 7.x所有版本 本文所有配置与代码均 ...
- Spring Boot 结合 Redis 序列化配置的一些问题
前言 最近在学习Spring Boot结合Redis时看了一些网上的教程,发现这些教程要么比较老,要么不知道从哪抄得,运行起来有问题.这里分享一下我最新学到的写法 默认情况下,Spring 为我们提供 ...
- 【Weiss】【第03章】练习3.20:中缀表达式转后缀表达式
[练习3.20] a.编写一个程序将中缀表达式转换为后缀表达式,该中缀表达式含括号及四则运算. b.把幂操作符添加到你的指令系统中去. c.编写一个程序将后缀表达式转化为中缀表达式. Answer: ...
- 《前端之路》- TypeScript (三) ES5 中实现继承、类以及原理
目录 一.先讲讲 ES5 中构造函数(类)静态方法和多态 1-1 JS 中原型以及原型链 例子一 1-2 JS 中原型以及原型链中,我们常见的 constructor.prototype.**prot ...
- 配置GitLab或Git环境之教程
配置GitLab或Git环境之教程 1.安装好Git后,首先打开开始菜单的所有程序里面的git文件夹,打开Git Bash/ 2.弹出的命令行里面输入ssh-keygen 输入y,一直Enter ...
- JVM收集器简介
JVM GC收集器集合:
- 4L-线性表之数组
关注公众号 MageByte,设置星标点「在看」是我们创造好文的动力.后台回复 "加群" 进入技术交流群获更多技术成长. 数组对于每一门编程语言来说都是重要的数据结构之一,当然不同 ...