nginx 处理客户端请求的完整过程

Nginx/Web服务器
459
0
0
2022-09-22
标签   Nginx原理

nginx 接收客户端连接

——> 接收数据,判断是否构成完整 http 消息

—是—> 判断是否转交 php-fpm 处理

—是—> 有选择地(请求行和部分消息头是专门给 nginx 看的,可能会剔除)将 http 消息发送给 php-fpm ——> php-fpm 主程序创建子进程

——> 子进程将 http 消息更新超全局数组(也可能是主程序做),引入 php 入口文件,返回 http 响应给主程序

——> php-fpm 主程序将 http 响应消息返回给 nginx

——> nginx 将 http 响应消息返给客户端,并决定是否关闭连接(在响应头 Connection 字段通知客户端)

nginx + php-fpm 的处理流程和 workerman 有什么重大的区别?
  • php-fpm 创建子进程处理请求,一个子进程处理一个请求,处理完关闭子进程。
  • workerman/hyperf/其它php服务器,创建子进程,但是子进程是独立的服务器,子进程接收客户端连接、数据、解出完整请求消息,转化为 request 对象,经过应用程序得到 response 对象,再转成响应消息,最后发送给客户端。
  • php 服务器没有 php-fpm 的来一个请求创建关闭一次子进程的消耗。它的主程序只用来监听子进程服务器的运行与维护,发现子进程关闭后重新创建新的子进程。它的子进程,就做了 nginx + php-fpm 的事,同时没有频繁的更下级的子进程的创建关闭消耗。
  • nginx 转发客户端请求给 php-fpm 主程序;php-fpm 创建子进程处理请求;子进程引入 php 入口文件,通过业务逻辑将请求转成响应,返给主程序并关闭自身;php-fpm 主程序将子进程处理的响应返给 nginx;nginx 响应客户端。
  • workerman 主程序创建N(可配置)个各类(tcp/http/udp/unix/https/websocket…)子进程(相当于服务器);其中,http 子进程完成类似 nginx + php-fpm 功能
workerman 在性能上比 nginx+php-fpm 的优势
  1. 不需要像 nginx 和 php-fpm 那样本地端口通信
  2. 不需要像 php-fpm 那样创建子进程专门处理
  3. 数据常驻内存,数据单例化高,性能越来越快,不需要单独重复性引入所谓入口文件及对应整套逻辑,http 子进程监听某个端口(比如 80),接收客户端连接、数据,处理后返回数据给客户端
那它是怎么通信的呢
  • nginx 配置里9000 端口是 php-fpm 程序默认端口,nginx 应该和 php-fpm 保持了长连接;如果没有,那每次请求连一次,太愚蠢了,nginx 监听了 80 端口,它内部有连接 9000 端口的套接字(对 php-fpm 来说,nginx 是客户端)
  • nginx 的主套接字监听 80 端口,有客户端完整请求时,它通过连接 9000 端口的套接字转发数据给 php-fpm
  • 主套接字监听端口,是等别人来找你(服务端);连接其它软件的端口的套接字,是找别人(客户端)两个套接字,套接字也是文件资源句柄,一个守着 80 端口等用户发请求过来,一个把请求转发给 php-fpm 监听的 9000 端口
  • 本机进程间通信,也叫 ip 换回连接,本机程序通信还有 unix ,就是监听 .sock 文件,数据传输在监听文件上表现,tcp 环回连接 性能不如 unix 连接
关于协议
  • -udp 和 tcp 都是基于 ip 协议,但是 udp 没有 tcp 三次握手(建立连接);
  • udp 因为没有连接,数据发送接收速度快;但是也因为没有连接,所以数据不知道从什么时候开始算,只能将一次数据当作一个完整消息,如果缺损,这次数据就报废了,所以不安全
  • tcp 因为有连接,如果数据包解析错误,客户端接收到相应提示,可以重新发送,服务端可以丢弃废数据重新接收解析,所以更安全
  • https 协议 基于 http 协议基于 tcp 协议 基于 ip 协议
  • websocket 协议(有一个额外握手,基于 http 协议格式)基于 tcp 协议
tcp的拆包粘包

拆包(接收到不完整包数据)

  1. 发送的数据大于套接字缓冲区剩余大小
  2. 发送的数据大于MTU(最大传输单元)大小

粘包(接收到多个包数据)

  1. 发送端:Nagle 算法判断前包数据过小,等待小段时间,同后包一起发送
  2. 接收端:前包缓存未读完,后包又到,不能区分前后包

本质问题:接收端无法区分包界限

解决方案:

  1. 消息数据定长,不足补空格;缺点是浪费内存和带宽
  2. 消息数据采用特定分隔符区分界限
  3. 消息数据分头和体,头部带消息长度,接收方根据头中长度解析数据