engine上实现了dyups,来实现对upstream的动态load,即在不重启nginx的情况下,完成对upstream的动态加载。
我们今天讨论的问题有些类似,那就是如何实现动态server的加载,即让一段一段的server{}热生效。
我们先梳理一下目前静态server{}的加载流程,它是在ngx_init_cycle里完成的
- 解析配置文件nginx.conf。解析的过程中会创建若干个ngx_http_srv_conf_conf_t对象(一个server对应一个)。对应的,每个http模块也会做相应的初始化,其context有时是srv,有时时loc。
- 为所有模块创建共享内存,在各个模块的create_main_conf回掉里会指定创建的大小,标志等等
- 创建好共享内存候回掉各个模块,说共享内存创建好了,as you wish,请使用
- 删除旧的listening,可以这次不开始443端口了
- 开始监听listening socket
大致就是上面的过程。
如果我们使用dyups的思路搞这个事情的话。比如每个worker可以加载一段server{}代码到自己的cycle中
1 | { |
加载这样的配置块,如果想生效,需要执行哪些步骤呢?共享内存和开启监听
第一步,肯定需要解析配置,创建ngx_http_srv_conf_conf_t,以及解析其内配置的各个模块命令
第二步,准备共享内存,通常是不需要的,因为共享内存都是在create_main_conf里创建,以及在shm等回掉里初始化,在当前的时机里,shm肯定初始化过了,shm和server{}无关,只和模块的main conf即http{}有关
第三步,开启监听以及相关事宜
第三步内容很复杂,可以考虑我的 nginx的配置管理 一文。但这部分对于某些方案来说,还是略有便利的。比如lvs + nginx这种架构。nginx上的监听,不是普普通通的监听,它是监听了一个大众socket,比如80,
所有的用户都使用这个80port,那如何区分从lvs的那个vs过来的流量呢?答案就是通过tcp option。
所以对于这样的case 第三步只是维护了一个虚假的监听,用户匹配从tcp option上拿到vs的信息即可。