Nginx 动态发现方案与实践

栏目: IT技术 · 发布时间: 5年前

内容简介:Nginx 动态发现方案与实践

Nginx 动态发现方案与实践

本文主要介绍了适用于nginx的zk动态后端发现模块(nginx-upstream-reloader)及其使用方法。

1.背景

很多公司都有做动态调度系统,有些是基于mesos+docker,有些采用了google的K8s,或者是自研的系统,这些系统有一个明显的特征就是服务实例的ip会频繁更换。

这种容器化的部署方式和传统的服务部署形式不一样,原有的服务都是部署在某些物理机或者云主机上,这些物理机或者云主机的ip地址不会轻易更换,这样我们配置nginx做流量转发的时候就可以直接写ip。

但是切换到这些容器化的系统后,服务的实例重启频繁,每一次重启后实例的ip就会发生变化,这样我们再用手动配置、变更后端ip的形式来做 nginx 的流量转发就基本上不可行了。

这时我们需要想办法让发布后的实例ip自动更新到nginx的配置中去,并且能够让其自动生效。

本模块正是基于前面的应用场景,用于解决后端实例ip频繁变化,无法将更新实时同步至nginx的配置中的问题。

2. 模块架构

前期通过调研发现,有些公司采用了etcd/consul+nginx第三方模块(nginx-upsync-module)的方式来实现nginx零重启更新upstream的操作。

我们内部并没有采用etcd或者consul来存储后端实例配置,而是广泛采用了zk服务来保存后端的配置。大部分业务都会将实例ip注册到zk中去,所以我们的nginx需要从zk中拉取后端实例ip和端口。

我们公司内部也有同学开发了nginx连接zk的模块,但是该模块是通过每个worker进程去连接zk,一个nginx可能有多个甚至几十个worker进程,会造成zk的连接数突增,给zk集群带来很大的压力。

后续通过调研发现了dyups这个模块,然后通过自己编码实现连接zk,从zk中拉取配置,再通过dyups模块的接口更新到upstream的共享内存,也可以实现零重启更新nginx的upstream列表。同时通过自己编码实现和zk交互的逻辑,也可以控制在zk不可用时执行的逻辑。

在我们的模块有用到dyups这个nginx模块,dyups模块是一个能够直接更新正在运行的nginx的upstream列表而不需要重新reload nginx配置的模块。

这个模块通过开放一个接口,然后外部通过这个接口发起post或者get请求,直接更新或者获取对应upstream的后端列表。

更加详细的用法可以浏览网址https://github.com/yzprofile/ngx_http_dyups_module查看这个模块的github介绍。

但是由于dyups模块只能修改nginx的共享内存,不能持久化当前的upstream配置到文件中,所以我们的模块另外一个核心的工作就是持久化upstream配置到配置文件中。

3. 模块功能

本模块结合了我们公司常见业务的应用场景、日常使用中碰到的问题以及dyups的不足之处,主要实现了如下几个功能:

1)获取注册到zk中后端列表,并对获取到的列表数据格式化,保存到相应的nginx配置文件中,进行持久化

2)将保存到文件的后端服务器列表通过dyups模块的接口写入到nginx upstream模块的共享内存中,动态更新upstream里面的后端列表

3)当zk故障时,本模块将不再更新nginx的共享内存和本地nginx配置文件,使nginx的upstream配置保持在zk故障前的状态

4)支持读取多个zk集群的多个zk节点配置

4. 模块工作流程

Nginx 动态发现方案与实践

5. 模块的使用

基础依赖:

支持dyups模块的nginx

python 2.6/2.7

1 clone模块代码到nginx机器上
这里我们将模块代码放到/home/work目录下

cd /home/work git clone http://v9.git.n.xiaomi.com/liuliqiu/nginx-upstream-reloader.git

2 执行模块源码目录中依赖安装脚本(nginx-upstream-reloader/install_venv.sh),这个脚本主要用于安装virtualvenv环境和依赖的第三方模块

cd nginx-upstream-reloader bash install_venv.sh

3 修改nginx-upstream-reloader模块配置文件
venv环境安装完成后,修改nginx-upstream-reloader/conf目录下的upstream_zk_nodes.conf 配置文件,这个配置文件用于定义后端实例所在的目的zk集群和zk节点以及对应nginx upstream的名字,具体的修改方法分为如下两种情况:

1)多个后端服务注册在一个zk集群,按照如下配置

upstream_zk_nodes.conf zk_servers:  zk-hadoop-test01:11000,zk-hadoop-test02:11000 zk_nodes:    bonus-api: /web_services/com.miui.bonus.api.resin-web

zk_servers:后端服务注册的zk集群地址和端口

zk_nodes:upstream_name:后端服务注册的zk节点路径

当我们启动后,模块会拉取指定zk节点路径下的后端列表信息自动生成upstream_name.upstream文件,

如上述配置,我们在指定的目录下(这个指定的目录可以在nginx-upstream-reloader/conf/main.conf配置文件的files_output_path选项控制,这里我们将该选项为/home/work/nginx/site-enable)/home/work/nginx/site-enable下会生成一个bonus-api.upstream文件,文件的内容会如下:

upstream bonus-api {    server ....;    server ....; }

2)多个后端服务器注册在不同的zk集群

upstream_zk_nodes.conf - zk_servers: tjwqstaging.zk.hadoop.srv:11000  zk_nodes:    ocean-helloworld-upstream1: /ocean/services/job.ocean-helloworld-nginx-upstream_service.ocean-helloworld-nginx-upstream_cluster.staging_pdl.oceantest_owt.inf_cop.xiaomi    ocean-helloworld-upstream2: /ocean/services/job.ocean-helloworld-nginx-upstream_service.ocean-helloworld-nginx-upstream_cluster.staging_pdl.oceantest_owt.inf_cop.xiaomi - zk_servers: tjwqstaging.zk.hadoop.srv:11000  zk_nodes:    ocean-helloworld-upstream3: /ocean/services/job.ocean-helloworld-nginx-upstream_service.ocean-helloworld-nginx-upstream_cluster.staging_pdl.oceantest_owt.inf_cop.xiaomi

zk_servers:后端服务注册的zk集群地址和端口

zk_nodes upstream_name:后端服务注册的zk节点路径

有同学跟我反馈为什么要用yaml格式的配置文件,而不用json格式的配置文件,json对格式要求没有yaml严格,但是yaml的配置文件看起层级直观多了。

当我们启动该模块后,模块会拉取指定zk节点路径下的后端列表信息自动生成upstream_name.upstream文件,如上述配置,模块在/home/work/nginx/site-enable会生成一个ocean-helloworld-upstream1.upstream、ocean-helloworld-upstream2.upstream、ocean-helloworld-upstream3.upstream三个文件,文件的内容会分别如下:

upstream ocean-helloworld-upstream1 {    server ...;    server ...; } upstream ocean-helloworld-upstream2 {    server ...;    server ...; } upstream ocean-helloworld-upstream3 {    server ...;    server ...; }

4 修改nginx配置文件
前面已经配置了nginx-upstream-reloader模块连接zk节点获取后端配置后,自动生成upstream配置文件,所以我们需要在nginx中include这些upstream配置文件在server块中才可以使用这些upstream。目前由于dyups模块的限制,需要将upstream_name设置为一个变量,然后在proxy_pass指令中使用这个变量配置转发,具体可以参考下面的配置:

include /home/work/nginx/site-enable/ocean-helloword-upstream1.upstream; include /home/work/nginx/site-enable/ocean-helloword-upstream2.upstream; include /home/work/nginx/site-enable/ocean-helloword-upstream3.upstream; server {        listen   80;        location /helloworld1 {                set $ups1 ocean-helloword-upstream1;                proxy_pass http://$ups;        }        location /helloworld2 {                set $ups2 ocean-helloword-upstream2;                proxy_pass http://$ups2;        }        location /helloworld3 {                set $ups3 ocean-helloword-upstream3;                proxy_pass http://$ups3;        } }

5 修改nginx配置文件,开启dyups接口
这里添加一个单独的server,监听本地地址的14443端口

server{    listen 127.0.0.1:14443;    server_name _;    location / {        dyups_interface;    } }

6 启动zk动态发现模块和nginx
这里需要先执行nginx-upstream-reloader/start.sh文件,启动nginx-upstream-reloader模块,然后再启动nginx,因为当我们还没有启动upstream-reloader模块时,upstream配置文件还未生成,但我们nginx配置文件中已经include这些upstream配置文件,这时启动nginx就会报错

bash nginx-upstream-reloader/start.sh /home/work/nginx/sbin/nginx #这里假设我们的nginx安装在/home/work/nginx/目录下

6. 兼容性

目前该模块已经在centos6和centos7上测试通过,适用于容器和物理机。

本文转自公众号:小米运维(ID:MI-SRE)

原文链接:Nginx动态发现方案与实践

“百万并发下的 Nginx 优化之道”

明星导师“陶辉” GOPS 2019 · 深圳站将带来

什么精彩议题?

敬请期待

Nginx 动态发现方案与实践

还有更多明星讲师亮相 GOPS 2019 · 深圳站…

点击阅读原文,了解更多精彩


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Professional JavaScript for Web Developers

Professional JavaScript for Web Developers

Nicholas C. Zakas / Wrox / 2009-1-14 / USD 49.99

This eagerly anticipated update to the breakout book on JavaScript offers you an in-depth look at the numerous advances to the techniques and technology of the JavaScript language. You'll see why Java......一起来看看 《Professional JavaScript for Web Developers》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试