Permalink: 2014-04-28 16:46:45 by ning in redis tags: all

配置热加载:

case SIGUSR2:

1   nginx 怎么做的

nginx 有两种情况:

  1. 配置修改
  2. 热升级二进制

1.1   配置修改

难点在于:

因为不能由各个子进程分别做监听, 只能父进程监听后, 确定监听sokcet列表, 然后fork出子进程, 由子进程继承监听socket.

1.1.1   过程

启动后:

+-------------------------------+
|               0               |
+-------------------------------+
  |       |
+---+   +---+
|   |   |   |
| 1 |   | 2 |
|   |   |   |
+---+   +---+

向父进程0发信号, 派生出新的子进程:

+-------------------------------+
|               0               |
+-------------------------------+
  |       |         a|       |
+---+   +---+      +---+   +---+
|   |   |   |      |   |   |   |
| 1 |   | 2 |      | 3 |   | 4 |
|   |   |   |      |   |   |   |
+---+   +---+      +---+   +---+

父进程收到信号后, 解析新的配置, 得到新的需要监听的列表, 以及每个监听socket对应的配置, 并派生新worker, 新worker启动后, 向老worker 发送优雅关闭的信号即可, 最后达到这样:

+-------------------------------+
|               0               |
+-------------------------------+
                    a|       |
                   +---+   +---+
                   |   |   |   |
                   | 3 |   | 4 |
                   |   |   |   |
                   +---+   +---+

1.1.2   细节

考虑父进程收到信号后, 派生新worker的过程. 假设

  • 旧配置监听8000, 8001, 8002几个port,
  • 新配置监听8000, 8001, 8003.

那么父进程解析完新的配置文件后, 会对比监听列表, 决定关闭8002, 新开8003, 保留8000, 8001, 然后把这三个fd开着, fork出新worker.

新worker 直接使用新的配置结构即可.

这里父进程可以直接修改自己的老配置为新配置(不会影响到 老的worker自己的那一份老配置)

对于twemporxy这样单进程模型, 就不能这样做, 如果在运行时修改自己的配置, 一个请求很可能跨两种不同的配置. 这就容易出问题.

1.2   热升级二进制

1.2.1   过程

+-------------------------------+
|               0               |
+-------------------------------+
  |       |
+---+   +---+
|   |   |   |
| 1 |   | 2 |
|   |   |   |
+---+   +---+

发信号:

+-------------------------------+
|               0               |
+-------------------------------+
  |       |                 |
+---+   +---+    +----------------------+
|   |   |   |    |          3           |
| 1 |   | 2 |    +----------------------+
|   |   |   |          |       |
+---+   +---+        +---+   +---+
                     |   |   |   |
                     | 4 |   | 5 |
                     |   |   |   |
                     +---+   +---+

发信号后0派生出一个新的master 3, 这个过程会把所有老的fd传给3, 由3来决定把哪些fd关掉. 新开哪些fd, 之后3会派生自己的worker.

0和3之间传递fd是通过环境变量来做的, 0会向环境变量里面写:

fds=3:8:72

这样的, 表示这三个listen fd, 子进程拿到这三个fd, 解析自己的配置, 看需要监听哪些端口, 和这些fd对比(这些fd可以通过getsockaddr获取所监听的端口)

2   关键点

传递fd:

3   应该做到怎样

配置:

  1. 增加pool
  2. pool属性变化.
  3. 减少pool.
  • 思路1: 改造tw为master-worker模式.
  • 思路2: 派生新进程, 通过环境变量来传递fd.

Comments