Nginx

Nginx相关知识

Posted by ZBX on September 17, 2020

Nginx

nginx 通过 多进程 + io多路复用(epoll) 实现了高并发 采用多个worker 进程实现对 多cpu 的利用 通过eopll 对 多个文件描述符 事件回调机制和就绪描述符的处理 实现单线程io复用 从而实现高并发

多进程

​ 解析初始化配置文件后,创建(fork)一个master进程之后,这个进程会退出,master进程会变为孤儿进程,由init进程托管。

master进程

​ 首先Nginx创建一个master进程,通过socket()创建一个sock文件描述符用来监听(sockfd)绑定端口(bind)开启监听(listen)。nginx 一般监听80(http) 或 443 (https)端口 (fork 多个子进程后,master 会监听worker进程,和等待信号)

worker进程

创建(fork)多个worker子进程(复制master进程的数据),此时所有的worker进程继承了sockfd(socket文件描述符),当有连接进程之后,worker进程就可以accept()创建已连接描述符,然后通过已连接描述符与客户端通讯。

  • 惊群现象
由于worker进程 继承了master进程的sockfd,当连接进来是,所有的子进程都将收到通知并“争着”与
它建立连接,这就叫惊群现象。大量的进程被激活又挂起,最后只有一个进程accpet() 到这个连接,这会消耗系统资源
(等待通知,进程被内核全部唤醒,只有一个进程accept成功,其他进程又休眠。这种浪费现象叫惊群)
  • nginx 对惊群现象的处理
原因:
    多个进程监听同一个端口引发的。
解决:
    如果可以同一时刻只能有一个进程监听端口,这样就不会发生“惊群”了,此时新连接事件只能唤醒正在监听的唯一进程。
    如何保持一个时刻只能有一个worker进程监听端口呢?nginx设置了一个accept_mutex锁,在使用accept_mutex锁是,
    只有进程成功调用了ngx_trylock_accept_mutex方法获取锁后才可以监听端口

(linux 内核2.6 之后 不会出现惊群现象,只会有一个进程被唤醒)

IO多路复用

epoll

1、创建一个epoll 对象,向epoll 对象中添加文件描述符以及我们所关心的在在该文件描述符上发生的事件 2、通过epoll_ctl 向我们需要关心的文件描述符中注册事件(读,写,异常等), 操作系统将该事件和对象的文件描述符作为一个节点插入到底层建立的红黑树中

3、添加到文件描述符上的实际都会与网卡建立回调机制,也就是实际发生时会自主调用一个回调方法, 将事件所在的文件描述符插入到就绪队列中

4、引用程序调用epoll_wait 就可以直接从就绪队列中将所有就绪的文件描述符拿到,可以说时间复杂度O(1)