nginx进程间通信机制
文章首发于公众号 松花皮蛋的黑板报
作者就职于京东,在稳定性保障、敏捷开发、高级JAVA、微服务架构有深入的理解
nginx使用到的进程间通信机制有三种,信号、套接字、共享内存。
一、信号
在nginx当中,信号是操作系统与master进程的通信方式。信号是用来控制master进程的一种手段。包括多钟不同的关闭nginx的方式,更新应用配置文件等。具体在nginx当中常用的信号如下表所示。
TERM, INT | 快速关闭,相当于nginx -s stop |
QUIT | 等待work进程处理完现有请求后,再关闭,相当于相当于nginx -s quit |
HUP | 重新加载配置文件,相当于nginx -s reload |
USR1 | 重新打开日志文件,相当于nginx -s reopen |
USR2 | 平滑升级nginx |
WINCH | 关闭工作进程(等待work进程处理完现有请求后) |
QUIT:关闭监听套接字,不接受新的连接请求,处理完旧的请求再关闭。
HUP:该信号发送到master进程,master先检查配置文件的语法,如果正确则打开新的日志文件和监听套接字,若此过程失败则会回滚并继续旧配置,如果此过程成功,则会启动新的工作进程。
USER1:该信号常用于nginx切割日志时,重新打开日志文件,当master进程收到该信号后,会重新打开配置文件中配置的日志文件,如果日志文件不存在则会新建一个日志文件。因为worker进程需要有对日志文件的读写权限,所以如果master和worker的用户不一致,则需要把日志文件的拥有者改成worker进程。然后master进程关闭旧日志文件,并通知worker进程使用新的日志文件,实际的操作就是,master进程把USER1信号发给worker进程,worker进程接收到信号后,重新打开日志文件。
USER2:平滑升级nginx
操作步骤:
1.发送信号给master进程
kill -USR2 $(cat /export/kong/pids/nginx.pid)
这一步会将.pid文件重命名为.oldbin,然后,执行
2.启动新版本nginx
3.结束旧版本master进程
kill -QUIT $(cat /export/kong/pids/nginx.pid)
二、套接字
套接字是master进程和worker进程通信的方式,但是目前只有master通过套接字发送消息给worker进程,还未用于worker进程发送消息给master进程。
举例来说,当nginx启动时,
1)master创建socket对
master在fork worker进程前,先调用socketpair,创建一个socket对用来master与worker进程间的通信。这个socket就是一个元素个数为2的数组channel,channel[0]用于master进程写入,channel[1]用于worker进程读入。
2)master创建worker进程
master进程根据配置文件中设置的worker进程数创建work进程。
3)worker进程将套接字加入epoll中
这样worker进程在处理http请求时也可以接收到master进程向它发送的消息了。
4)worker进程循环
三、共享内存
共享内存是最快的通信方式,是worker进程之间的通信方式。需要共享的数据就需要用到共享内存,例如,http连接数,每个worker进程修改的都是共享内存中的数据,该数据是全局变量,对所有的worker进程是共享的。
nginx通过ngx_shm_t这个结构体管理共享内存,方法只有分配和释放。nginx对linux的分配内存 mmap和释放内存方法munmap进行了封装,不一样的地方是nginx不从文件中映射,只从内存中开辟一段连续的地址空间作为共享内存。封装后的nginx分配内存方法是 ngx_shm_alloc,释放内存方法是 ngx_shm_free。
其实master和worker进程也能通过共享内存通信,在master进程fork worker进程之前,先在内存中开辟一块共享内存,并且映射到自己进程地址空间中的共享内存区,然后,调用fork,这样派生出来的worker进程可以继承到这块共享内存区,这样master和worker之间也可以通过共享内存通信。
文章来源:www.liangsonghua.me
作者介绍:京东资深工程师-梁松华,在稳定性保障、敏捷开发、JAVA高级、微服务架构方面有深入的理解