leevis.com icon indicating copy to clipboard operation
leevis.com copied to clipboard

nginx 动态upstream

Open vislee opened this issue 8 years ago • 1 comments

概述

upstream的server 支持配置域名。但是只是在启动的时候调用了glibc的getaddrinfo函数解析的,而不是通过reslover配置的域名服务器解析的。具体细节请看《nginx 域名动态解析》。

当域名对应的地址有变化时,nginx是不会自动更新的,只能通过重启nginx来解决。其实官方商业版是提供了解决方案的。在server这个指令提供了个resolve参数用来动态解析地址。就是说server配置的域名解析有更新,不用重启nginx了。商业版本不仅提供了动态解析,还可以通过REST API来修改upstream的server。

实现

本人参考官方文档实现了一个模块,提供域名动态解析和REST API来修改upstream的server。 目前还处于测试阶段。大概先说一下实现思路。 nginx主线版本从1.9.0开源了一个ngx_http_upstream_zone_module模块。该模块在upstream这个block提供了一个zone指令。用来把upstream的信息保存到共享内存中。仅此而已,没有开源任何相关的用途。

那我们就可以基于该模块来实现域名动态解析和REST API。nginx的很多函数都是回调函数,在赋值和调用过程中我们可以嵌入我们的模块修改回调函数赋值,从而把我们的逻辑加入到nginx中。

upstream这个block有好多负载均衡策略的配置,例如ip_hash,我们可以参考该实现来把自己的实现嵌入到nginx中。 我们在upstream这个block提供一个指令server_resolver,在该指令的实现函数中把uscf->peer.init_upstream 回调修改成我们自己的实现ngx_http_upstream_init_resolver,从而把我们自己的逻辑嵌入到nginx中。该回调是在ngx_http_upstream_init_main_conf函数中被调用的。

回调函数也可以参考ip_hash的实现,先调用原来peer.init_upstream的回调函数初始化上游服务器。然后把我们的实现ngx_http_upstream_init_resolver_peer赋值us->peer.init函数指针么,在ngx_http_upstream_init_request函数中被调用。

我们可以在该函数ngx_http_upstream_init_resolver_peer中就实现解析域名。也可以继续赋值在upstream->peer.get或upstream->peer.free中解析域名。目前实现是在该函数就解析域名了。

在该函数ngx_http_upstream_init_resolver_peer中主要的任务是赋值负载均衡策略的回调函数,然后找一个需要解析的域名发起域名解析请求,并赋值好回调函数。从此域名解析就脱离upstream机制,当域名解析结果返回时调用添加的回调函数。把解析结果添加到upstream的server的共享内存中。销毁域名解析相关结构体和函数。

参考: http://nginx.org/en/docs/http/ngx_http_upstream_module.html http://nginx.org/en/docs/http/ngx_http_api_module.html

vislee avatar Jan 15 '18 08:01 vislee

关注中. 期待开源.

selboo avatar Jan 15 '18 08:01 selboo