17《Nginx 入门教程》Nginx 的基础架构解析(上)

1. Nginx 的进程模型

前面介绍 Nginx 时有介绍过 Nginx 的进程模型。Nginx 启动时首先启动一个 Master 进程,然后由 Master 进程启动一个或者多个 Worker 子进程。Master 进程主要完成配置读取,通过发送信号控制 Worker 进程的启动和停止等,而 Worker 子进程是用来处理客户端发来的 Http 请求,且Worker进程之间会通过共享内存进行通信。

1.1 worker 进程处理请求过程

假设 Nginx 启动了多个 Worker 进程,并且在 Master 进程中通过 socket 套接字监听80端口。
这些 Worker 进程 fork 自 Master 进程,然后每个worker进程都可以去 accept 这个监听的 socket。 当一个连接进来后,所有在 accept 在这个 socket 上面的进程,都会收到消息,但是只有一个进程可以 accept 这个连接,其它的则 accept 失败,这便是所谓的惊群现象。Nginx 处理这种情况的方式就是加锁。有了锁之后,在同一时刻,就只会有一个 Worker 进程在 accpet 连接,这样就不会有惊群问题了。在 Worker 进程拿到 Http 请求后,就开始按照前面介绍的 11个阶段处理该 Http 请求,最后返回响应结果并断开连接。

1.2 Nginx 命令行的处理流程

最早我们学习了 Nginx 命令行操作,这些命令行操作都是给 Master 进程发信号,然后再由 Master 进程发送信号给 Worker 进程,从而达到控制 Worker 进程的目标。我们以 Nginx 的热部署命令./nginx -s reload 来描述 Nginx 命令行的执行流程。具体过程如下:

  • 首先 Master 进程会检查 nginx.conf 文件是否存在语法错误,并从中找到 nginx.pid 配置路径(没有配置会使用默认值)
  • reload 参数表示向 Master 进程发送 HUP 信号。Nginx 会根据会保存在 nginx.pid 文件中的值找到 Master 进程的 pid。如果 Nginx 进程没有启动,则没有该 nginx.pid 文件,命令行会报错;
# 在 Nginx 的配置文件中配置 nginx.pid 的保存路径
[root@server sbin]# ./nginx -s reload
nginx: [error] open() "/root/nginx/logs/nginx.pid" failed (2: No such file or directory)

  • Master 进程打开新的监听端口;
  • Master 进程用新配置启动新的 Worker 进程。新的 Worker 进程起来后,开始接收 Http 请求并处理,此时老的 Worker进程会停止接受 Http 请求;
  • Master 进程会向老的 Worker进程发送 QUIT 信号;
  • 老的 Worker 进程关闭监听句柄,处理完正在进行的请求后结束进程。

Nginx 命令行中 -s 参数的每个值都对应这一个信号。因此,我们也可以直接对 Master 进程发生相应信号达到同样的目的。

# pid表示Nginx的主进程id号
# kill -s 信号 pid

2. Nginx的事件驱动模型

2.1 事件驱动模型

事件驱动模型是实现异步非阻塞的一个手段。对于 web 服务器来说,客户端 A 的请求连接到服务端时,服务端的某个进程(Nginx 的 worker 进程)会处理该请求,此进程在没有返回给客户端 A 结果时,它又去处理了客户端 B 的请求。服务端把客户端 A 以及客户端 B 发来的请求作为事件交给了"事件收集器",而"事件收集器"再把收集到的事件交由"事件发送器"发送给"事件处理器"进行处理。最后"事件处理器"处理完该事件后,通知服务端进程,服务端进程再把结果返回给客户端A、客户端B。在这个过程中,服务端进程做的事情属于用户级别的,而事件处理这部分工作属于内核级别的。也就是说这个事件驱动模型是需要操作系统内核来作为支撑的。

2.2 Nginx的事件驱动模型介绍

Nginx 的事件驱动模型,支持 select、poll、epoll、rtsig、kqueue、/dev/poll、eventport 等。
最常用的是前三种,特别是 epoll 模型,这也是 Nginx 中的默认配置。可以说 epoll 模型成就了 Nginx 的高性能和高并发特性。

  • select模型:
    • 创建所关注事件的描述符集合,对于一个描述符,可以关注其上面的读(Read)事件、写(Write)事件以及异常发生(Exception)事件。
      在select模型中,要创建这3类事件描述符集合。
    • 调用底层提供的select()函数,等待事件发生。
    • 轮询所有事件描述符集合中的每一个事件描述符,检查是否有相应的事件发生,如果有就进行处理。
  • poll模型:
    • poll模型是Linux平台上的事件驱动模型,在Linux2.1.23中引入的,Windows平台不支持该模型。
    • poll模型和select模型工作方式基本相同,区别在于,select模型创建了3个描述符集合,而poll模型只创建一个描述符集合。
  • epoll模型:
    • epoll模型属于poll模型的变种,在Linux2.5.44中引入。epoll比poll更加高效,原因在于它不需要轮询整个描述符集合,而是Linux内核会关注事件集合,当有变动时,内核会发来通知。
    • 正式这种异步,非阻塞、IO多路复用的事件驱动模型,才使得 Nginx 有很高的运行效率。

3. 案例

3.1 Nginx 进程模型实验

按照前面的讲解,我们测试给 Nginx 的 Master 进程直接发送信号,并观察进程情况:

# 确认没有 Nginx 进程
[root@server sbin]# ps -ef | grep nginx
root     10603 10137  0 14:23 pts/2    00:00:00 grep --color=auto nginx
# 启动 Nginx 
[root@server sbin]# ./nginx
# 可以看到 Nginx 启动的进程
[root@server sbin]# ps -ef | grep nginx
root     10640     1  0 14:23 ?        00:00:00 nginx: master process ./nginx
root     10642 10640  0 14:23 ?        00:00:00 nginx: worker process
root     10643 10640  0 14:23 ?        00:00:00 nginx: worker process
root     10644 10640  0 14:23 ?        00:00:00 nginx: cache manager process
root     10645 10640  0 14:23 ?        00:00:00 nginx: cache loader process

可以看到 Nginx 启动了 Master 进程(pid=10640),后由 Master 进程 fork 除了两个 Worker 进程和两个 Cache 进程,他们的父进程 id 均为10640。现在做如下几个操作:

  • 关闭进程号等于10642的 Worker 进程
[root@server sbin]# sudo kill -SIGTERM 10642
[root@server sbin]# ps -ef | grep nginx
root     10640     1  0 14:23 ?        00:00:00 nginx: master process ./nginx
root     10643 10640  0 14:23 ?        00:00:00 nginx: worker process
root     10644 10640  0 14:23 ?        00:00:00 nginx: cache manager process
root     10869 10640  0 14:32 ?        00:00:00 nginx: worker process
root     10939 10137  0 14:32 pts/2    00:00:00 grep --color=auto nginx

可以看到原先的 Worker 进程被杀死后,Nginx 的主进程又立马拉起来一个新的 Worker 进程提供服务。这说明 Nginx 是非常可靠的,只要 Master 进程还在就会保证 Worker 进程持续存在并提供服务。

  • 向主进程发送 SIGHUP 信号,等价于 -s reload 操作。可以看到除了 Master 进程外,所有其他进程已经是新启动的进程了。
[root@server sbin]# sudo kill -SIGHUP 10640
[root@server sbin]# ps -ef | grep nginx
root     10640     1  0 14:23 ?        00:00:00 nginx: master process ./nginx
root     11059 10640  0 14:37 ?        00:00:00 nginx: worker process
root     11060 10640  0 14:37 ?        00:00:00 nginx: worker process
root     11061 10640  0 14:37 ?        00:00:00 nginx: cache manager process
root     11098 10137  0 14:37 pts/2    00:00:00 grep --color=auto nginx

  • 向主进程发生 SIGTERM 信号,等价于 -s stop 操作,即停止 Nginx 服务,关闭所有进程
[root@server sbin]# sudo kill -SIGTERM 10640
[root@server sbin]# ps -ef | grep nginx
root     11267 10137  0 14:43 pts/2    00:00:00 grep --color=auto nginx

  • 向主进程发生 USR1 信号,等价于 -s repoen 操作,即重新打开日志文件
[root@server sbin]# ./nginx

[root@server sbin]# ps -ef | grep nginx
root     11408     1  0 14:48 ?        00:00:00 nginx: master process ./nginx
root     11410 11408  0 14:48 ?        00:00:00 nginx: worker process
root     11411 11408  0 14:48 ?        00:00:00 nginx: worker process
root     11412 11408  0 14:48 ?        00:00:00 nginx: cache manager process
root     11413 11408  0 14:48 ?        00:00:00 nginx: cache loader process
root     11484 10137  0 14:49 pts/2    00:00:00 grep --color=auto nginx

[root@server sbin]# ll ../logs/access.log 
-rw-r--r-- 1 root root 384349 Feb 11 14:26 ../logs/access.log

[root@server sbin]# rm -rf ../logs/access.log 

[root@server sbin]# ll ../logs/access.log 
ls: cannot access ../logs/access.log: No such file or directory

[root@server sbin]# kill -USR1 11408
[root@server sbin]# ll ../logs/access.log 
-rw-r--r-- 1 root root 0 Feb 11 14:50 ../logs/access.log


可以看到,在移除 Nginx 的 access.log 日志后,在向 Nginx 主进程发送 USR1 信号,Nginx 会重新生成一个新的 access.log 日志。

4. 小结

本节主要介绍 Nginx 的进程模型以及介绍了 Master 和 Worker 之间的通信过程。此外,我们介绍了 Nginx 的事件驱动模型。异步、多路IO复用、非阻塞等特点早就了 Nginx 的高性能。接下来,我们完成了 Nginx 进程模型的几个实验,直观体检 Nginx 的进程模型。下一节将重点介绍 Nginx 模块相关的内容,并手动实现一个简单的 http 模块。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容