赞
踩
1.网络收发与Nginx事件间的对应关系
- 主机A是我们家里的一台笔记本电脑,主机B是部署着Nginx的服务器,从主机A发送一个http的get请求
- 到主机B,在这样的过程中究竟经历了什么网络事件呢?
-
- 在数据流中,
- 1.主机A的应用层:发送一个http请求;
- 2.主机A的传输层:做一件事,浏览器打开一个端口,会将端口记下,并把Nginx打卡的端口比如说8080也记录到传输层;
- 3.主机A的网络层:记录我们主机A所在的IP和目标Nginx主机B的公网IP;
- 4.主机A的链路层:经过以太网到达我们家的路由器;
- 5.以太网->链路层->网络层->广域网->以太网:我们家的路由器会记录我们所在运营商的一些下一段的IP,经过广域网以后最终跳转到主机B所在的机器中;
- 6.主机B的链路层;
- 7.主机B的网络层;
- 8.主机B的传输层(此时操作系统知道是给打开了8080端口的进程,即主机B上的Nginx服务);
- 9.主机B的http状态处理机中就会处理这个请求.
-
- TCP流与报文:
- 数据链路层:添加源mac和目的mac地址;
- 网络层: 添加浏览器的公网IP和Nginx的公网IP;
- TCP层: 指定了Nginx打开的端口和浏览器打开的端口;
- 应用层: HTTP协议
-
- 经过这么多层的组装,组成了一个完整的可以在网络世界里遨游并寻找到目标进程的报文,
- 一个HTTP协议可以切割成很多小的报文:
- 网络层会切掉MTU(以太网的MTU是1500字节);
- TCP层会考虑中间每个环节中的最大的一个MTU值,这时往往我们每个报文只有几百字节,这个报文大小称作
- MSS,每收到一个MSS(小于MTU值)时,就是一个网络事件.

2.TCP协议与非阻塞接口
- 请求建立TCP连接事件(发送一个TCP报文,是一个读事件,对于Nginx来说读到了一个报文,Accept建立连接)
- TCP连接可读事件(发送了一个消息,对Nginx来说也是读事件,Read读事件)
- TCP连接关闭事件(关闭连接的一个事件,对Nginx来说也是读事件)
- TCP连接可写事件(对Nginx来说也是写事件)
- 异步读AIO磁盘成功事件(对Nginx来说也是读事件)
-
-
-
- 请求建立TCP连接事件---Nginx是连接建立事件消费者
- TCP连接可读事件 ---Nginx是读事件消费者
- TCP连接关闭事件 ---Nginx是连接关闭事件消费者
- TCP连接可写事件 ---Nginx是写事件消费者
- 异步读磁盘成功事件 ---Nginx是异步读磁盘事件消费者
- 以上事件触发定时器到期事件.
-
- 所以对于TCP协议来说,Nginx会有以上6种小类事件.
-

3.Nginx事件循环
- 当Nginx刚启动时,此时Nginx处于等待新的事件进来的状态(wait for evensts on connections),
- 比如说等待新的客户端连上我们的Nginx,向我们的Nginx发起连接请求,这个状态对应着epoll中的
- epoll_wait的一个方法,此时Nginx处于sleep的一个进程状态,当操作系统收到了一个建立tcp连接的
- 握手报文并且处理完握手流程以后,操作系统就会通知epoll_wait方法告诉它可以往下运行了,同时唤醒
- nginx的worker进程,往下走了之后就去找操作系统kernel中要事件,操作系统会把准备好的时间放在事件
- 队列中,从事件队列中可以获取到一个一个要处理的时间(如建立连接或者tcp的请求报文),将其从请求
- 队列中取出,取出之后,就会处理这样一个事件.
-
- 右图是处理事件的一个循环,发现队列中不为空,就将事件取出开始处理事件,在处理事件的过程中可能生成新的事件,比如说发现新的连接,
- 可能需要添加一个超时事件,比如说60秒,如果60秒之内如果浏览器不给我发送请求的话,就会把连接关掉,又比如说,当我发现我收完了完整的
- http请求后,已经可以生成http响应了,http响应是需要我可以向操作系统的写缓冲区中把响应写进去,要求操作系统尽快的把这段内容发到浏
- 览器上,此时就期待一个写事件;也就是说我们在处理事件的过程中可能会出现新的事件,生成新的队列,等待下一次来处理.如果所有的事件都
- 处理完成了,我们又会回到wait for evensts on connections这里.就有这样一个流程.
-
- 了解Nginx事件循环有助于我们分析一些场景,比如说使用一些第三方模块的时候,这些第三方模块可能会做
- 大量的CPU运算,这样的计算任务会导致处理一个事件的任务非常长,会导致后序队列中的大量事件长时间得不到
- 处理,从而引发恶性循环(其他事件的超时事件到了),大量CPU都消耗在这些处理上,导致其他的连接不正常的
- 断开,所以往往Nginx不能容忍有些第三方模块长时间地消耗大量的CPU进行计算任务.我们可以看到包括gzip等
- 第三方模块都不会一次使用大量的CPU,而是分段使用.

4.epoll的优劣和原理
- select,poll和epoll的一个质的关键飞跃就是:
- epoll能快速地从内核中得到需要操作的事件.
-
-
- 问题:为什么epoll的效率会比poll和select相对高?
- epoll维护了双向链表,双向链表中只有活跃的请求,不做无用功.
-
- 什么时候双向链表的数据会增减?
- 当我们读取一个数据的时候,这个数据就会从链表中删除;
- 当操作系统接收到网卡中发送来的一个报文的时候,这个链表就会增加一个新的元素.
- rdllink(ready的链表)
-
- epoll是一个网络事件收集器模型.
5.Nginx的请求切换
- 如图中传统的服务器中,比如说有三个处理流程,第一次不满足的时候,操作系统就通过内核切换到第二个
- 处理流程中,第二个不满足的时候,就通过内核切换到第三个流程中,此时轮到第一个流程运转了,再通过
- 内核切换到第一个流程中,一次切换大概需要5微妙,操作系统的进程调度这对于成百上千的请求来说还可以
- 接受,但是一旦并发量大起来,就会变得稍微难以接受.
-
- Nginx中如何处理进程间的切换呢?当蓝色部分不满的时候,直接就在用户态切换到了绿色的请求,这样就没有
- 了操作系统中的进程切换的成本--类似协程概念(因为网络事件不满足),除非Nginx的worker所使用的的时间片到了,
- 这样才去进行内核的进程切换,一般来说时间片的长度是5毫秒-800毫秒,在Nginx的配置上往往会将workrt进程的
- 优先级加到最高(-19),此时操作系统给我们分配的时间片是比较多的,这样Nginx可以在用户态完成请求的切换,
- 使得CPU少做无用功.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。