首页 运维 nginx nginx的请求如何处理?

nginx的请求如何处理?

Nov 28, 2019 pm 02:57 PM
nginx

nginx的请求如何处理?

今天我们讲 request,在 Nginx 中我们指的是 http 请求,具体到 Nginx 中的数据结构是ngx_http_request_t。ngx_http_request_t 是对一个 http 请求的封装。 我们知道,一个 http 请求,包含请求行、请求头、请求体、响应行、响应头、响应体。

http 请求是典型的请求-响应类型的的网络协议,而 http 是文本协议,所以我们在分析请求行与请求头,以及输出响应行与响应头,往往是一行一行的进行处理。       ( 推荐学习:nginx使用 )

如果我们自己来写一个 http 服务器,通常在一个连接建立好后,客户端会发送请求过来。然后我们读取一行数据,分析出请求行中包含的 method、uri、http_version 信息。

然后再一行一行处理请求头,并根据请求 method 与请求头的信息来决定是否有请求体以及请求体的长度,然后再去读取请求体。

得到请求后,我们处理请求产生需要输出的数据,然后再生成响应行,响应头以及响应体。

在将响应发送给客户端之后,一个完整的请求就处理完了。当然这是最简单的 webserver 的处理方式,其实 Nginx 也是这样做的,只是有一些小小的区别,比如,当请求头读取完成后,就开始进行请求的处理了。Nginx 通过 ngx_http_request_t 来保存解析请求与输出响应相关的数据。

那接下来,简要讲讲 Nginx 是如何处理一个完整的请求的。对于 Nginx 来说,一个请求是从ngx_http_init_request 开始的,在这个函数中,会设置读事件为 ngx_http_process_request_line,也就是说,接下来的网络事件,会由 ngx_http_process_request_line 来执行。

从ngx_http_process_request_line 的函数名,我们可以看到,这就是来处理请求行的,正好与之前讲的,处理请求的第一件事就是处理请求行是一致的。

通过 ngx_http_read_request_header 来读取请求数据。然后调用 ngx_http_parse_request_line 函数来解析请求行。Nginx 为提高效率,采用状态机来解析请求行,而且在进行 method 的比较时,没有直接使用字符串比较,而是将四个字符转换成一个整型,然后一次比较以减少 cpu 的指令数,这个前面有说过。

很多人可能很清楚一个请求行包含请求的方法,uri,版本,却不知道其实在请求行中,也是可以包含有 host 的。比如一个请求 GET http://www.taobao.com/uri HTTP/1.0 这样一个请求行也是合法的,而且 host 是 www.taobao.com,这个时候,Nginx 会忽略请求头中的 host 域,而以请求行中的这个为准来查找虚拟主机。

另外,对于对于 http0.9 版来说,是不支持请求头的,所以这里也是要特别的处理。所以,在后面解析请求头时,协议版本都是 1.0 或 1.1。整个请求行解析到的参数,会保存到 ngx_http_request_t 结构当中。

在解析完请求行后,Nginx 会设置读事件的 handler 为 ngx_http_process_request_headers,然后后续的请求就在 ngx_http_process_request_headers 中进行读取与解析。

ngx_http_process_request_headers 函数用来读取请求头,跟请求行一样,还是调用 ngx_http_read_request_header 来读取请求头,调用 ngx_http_parse_header_line 来解析一行请求头,解析到的请求头会保存到 ngx_http_request_t 的域 headers_in 中,headers_in 是一个链表结构,保存所有的请求头。

而 HTTP 中有些请求是需要特别处理的,这些请求头与请求处理函数存放在一个映射表里面,即 ngx_http_headers_in,在初始化时,会生成一个 hash 表,当每解析到一个请求头后,就会先在这个 hash 表中查找,如果有找到,则调用相应的处理函数来处理这个请求头。比如:Host 头的处理函数是 ngx_http_process_host。

当 Nginx 解析到两个回车换行符时,就表示请求头的结束,此时就会调用 ngx_http_process_request 来处理请求了。

ngx_http_process_request 会设置当前的连接的读写事件处理函数为 ngx_http_request_handler,然后再调用 ngx_http_handler 来真正开始处理一个完整的http请求。

这里可能比较奇怪,读写事件处理函数都是ngx_http_request_handler,其实在这个函数中,会根据当前事件是读事件还是写事件,分别调用 ngx_http_request_t 中的 read_event_handler 或者是 write_event_handler。

由于此时,我们的请求头已经读取完成了,之前有说过,Nginx 的做法是先不读取请求 body,所以这里面我们设置 read_event_handler 为 ngx_http_block_reading,即不读取数据了。

刚才说到,真正开始处理数据,是在 ngx_http_handler 这个函数里面,这个函数会设置 write_event_handler 为 ngx_http_core_run_phases,并执行 ngx_http_core_run_phases 函数。

ngx_http_core_run_phases 这个函数将执行多阶段请求处理,Nginx 将一个 http 请求的处理分为多个阶段,那么这个函数就是执行这些阶段来产生数据。

因为 ngx_http_core_run_phases 最后会产生数据,所以我们就很容易理解,为什么设置写事件的处理函数为 ngx_http_core_run_phases 了。

在这里,我简要说明了一下函数的调用逻辑,我们需要明白最终是调用 ngx_http_core_run_phases 来处理请求,产生的响应头会放在 ngx_http_request_t 的 headers_out 中,这一部分内容,我会放在请求处理流程里面去讲。Nginx 的各种阶段会对请求进行处理,最后会调用 filter 来过滤数据,对数据进行加工,如 truncked 传输、gzip 压缩等。

这里的 filter 包括 header filter 与 body filter,即对响应头或响应体进行处理。filter 是一个链表结构,分别有 header filter 与 body filter,先执行 header filter 中的所有 filter,然后再执行 body filter 中的所有 filter。

在 header filter 中的最后一个 filter,即 ngx_http_header_filter,这个 filter 将会遍历所有的响应头,最后需要输出的响应头在一个连续的内存,然后调用 ngx_http_write_filter 进行输出。

ngx_http_write_filter 是 body filter 中的最后一个,所以 Nginx 首先的 body 信息,在经过一系列的 body filter 之后,最后也会调用 ngx_http_write_filter 来进行输出(有图来说明)。

这里要注意的是,Nginx 会将整个请求头都放在一个 buffer 里面,这个 buffer 的大小通过配置项 client_header_buffer_size 来设置,如果用户的请求头太大,这个 buffer 装不下,那 Nginx 就会重新分配一个新的更大的 buffer 来装请求头,这个大 buffer 可以通过 large_client_header_buffers 来设置,这个 large_buffer 这一组 buffer,比如配置 48k,就是表示有四个 8k 大小的 buffer 可以用。

注意,为了保存请求行或请求头的完整性,一个完整的请求行或请求头,需要放在一个连续的内存里面,所以,一个完整的请求行或请求头,只会保存在一个 buffer 里面。

这样,如果请求行大于一个 buffer 的大小,就会返回 414 错误,如果一个请求头大小大于一个 buffer 大小,就会返回 400 错误。在了解了这些参数的值,以及 Nginx 实际的做法之后,在应用场景,我们就需要根据实际的需求来调整这些参数,来优化我们的程序了。

处理流程图:

nginx-42.png

以上这些,就是 Nginx 中一个 http 请求的生命周期了。

以上是nginx的请求如何处理?的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

docker容器名称怎么查 docker容器名称怎么查 Apr 15, 2025 pm 12:21 PM

可以通过以下步骤查询 Docker 容器名称:列出所有容器(docker ps)。筛选容器列表(使用 grep 命令)。获取容器名称(位于 "NAMES" 列中)。

nginx怎么查版本 nginx怎么查版本 Apr 14, 2025 am 11:57 AM

可以查询 Nginx 版本的方法有:使用 nginx -v 命令;查看 nginx.conf 文件中的 version 指令;打开 Nginx 错误页,查看页面的标题。

nginx怎么配置云服务器域名 nginx怎么配置云服务器域名 Apr 14, 2025 pm 12:18 PM

在云服务器上配置 Nginx 域名的方法:创建 A 记录,指向云服务器的公共 IP 地址。在 Nginx 配置文件中添加虚拟主机块,指定侦听端口、域名和网站根目录。重启 Nginx 以应用更改。访问域名测试配置。其他注意事项:安装 SSL 证书启用 HTTPS、确保防火墙允许 80 端口流量、等待 DNS 解析生效。

nginx在windows中怎么配置 nginx在windows中怎么配置 Apr 14, 2025 pm 12:57 PM

如何在 Windows 中配置 Nginx?安装 Nginx 并创建虚拟主机配置。修改主配置文件并包含虚拟主机配置。启动或重新加载 Nginx。测试配置并查看网站。选择性启用 SSL 并配置 SSL 证书。选择性设置防火墙允许 80 和 443 端口流量。

怎么查看nginx是否启动 怎么查看nginx是否启动 Apr 14, 2025 pm 01:03 PM

确认 Nginx 是否启动的方法:1. 使用命令行:systemctl status nginx(Linux/Unix)、netstat -ano | findstr 80(Windows);2. 检查端口 80 是否开放;3. 查看系统日志中 Nginx 启动消息;4. 使用第三方工具,如 Nagios、Zabbix、Icinga。

docker怎么启动容器 docker怎么启动容器 Apr 15, 2025 pm 12:27 PM

Docker 容器启动步骤:拉取容器镜像:运行 "docker pull [镜像名称]"。创建容器:使用 "docker create [选项] [镜像名称] [命令和参数]"。启动容器:执行 "docker start [容器名称或 ID]"。检查容器状态:通过 "docker ps" 验证容器是否正在运行。

怎么启动nginx服务器 怎么启动nginx服务器 Apr 14, 2025 pm 12:27 PM

启动 Nginx 服务器需要按照不同操作系统采取不同的步骤:Linux/Unix 系统:安装 Nginx 软件包(例如使用 apt-get 或 yum)。使用 systemctl 启动 Nginx 服务(例如 sudo systemctl start nginx)。Windows 系统:下载并安装 Windows 二进制文件。使用 nginx.exe 可执行文件启动 Nginx(例如 nginx.exe -c conf\nginx.conf)。无论使用哪种操作系统,您都可以通过访问服务器 IP

docker怎么创建容器 docker怎么创建容器 Apr 15, 2025 pm 12:18 PM

在 Docker 中创建容器: 1. 拉取镜像: docker pull [镜像名] 2. 创建容器: docker run [选项] [镜像名] [命令] 3. 启动容器: docker start [容器名]

See all articles