关于在nginx上实现dyserver的思路

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
2
3
4
5
6
7
8
9
10
{
server {
listen 80 default_server;
server_name _; # This is just an invalid value which will never trigger on a real hostname.
access_log logs/default.access.log main;
server_name_in_redirect off;
root /var/www/default/htdocs;
test_module_cmd on; // 一个新模块test_module,需要使用共享内存
}
}

加载这样的配置块,如果想生效,需要执行哪些步骤呢?共享内存和开启监听

第一步,肯定需要解析配置,创建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的信息即可。