http://www.yunweipai.com/archives/16211.html
Upsync是新浪微博开源的基于Nginx实现动态配置的三方模块。Nginx-Upsync-Module
的功能是拉取Consul的后端server的列表,并动态更新Nginx的路由信息。此模块不依赖于任何第三方模块。Consul作为Nginx的DB,利用Consul的KV服务,每个Nginx Work进程独立的去拉取各个upstream的配置,并更新各自的路由。
Upsync模块工作原理
在Nginx的设计中,每一个upstream维护了一张静态路由表,存储了backend的ip、port以及其他的meta信息。每次请求到达后,会依据location检索路由表,然后依据具体的调度算法(如round robin )选择一个backend转发请求。但这张路由表是静态的,如果变更后,则必须reload,经常reload的话这对SLA有较大影响。
为了达到减少reload的目的,大多通过动态更新维护路由表来解决这个问题。通常路由表的维护有Push与Pull两种方式。
- Push方案
通过Nginx API向Nginx发出请求,操作简单、便利。
架构图如下
http api除了操作简单、方便,而且实时性好;缺点是有多台Nginx时,不同Nginx路由表的一致性难于保证,如果某一条注册失败,便会造成服务配置的不一致,容错复杂。另外扩容Nginx服务器,需要从其他的Nginx中同步路由表。
- Pull方案
路由表中所有的backend信息(含meta)存储到Consul,所有的Nginx从Consul拉取相关信息。有变更则更新路由表,利用Consul解决一致性问题,同时利用Consul的wait机制解决实时性问题。利用Consul的index进行增量摘取,解决带宽占用问题。
在Consul中,一个K/V对代表一个backend信息,增加一个即视作扩容,减少一个即为缩容。调整meta信息,如权重,也可以达到动态流量调整的目的。
架构图如下:
- 基于动态路由的方案实现
Upsync模块使用了第二种模式,通过拉取Consul的后端Server的列表,并动态更新Nginx的路由信息。Upsync模块工作流程图如下:
每个Work进程定时的去Consul拉取相应upstream的配置,若Consul发现对应upstream的值没有变化,便会hang住这个请求五分钟(默认值)。在这五分钟内对此upstream的任何操作,都会立刻返回给Nginx对相应路由进行更新。
upstream变更后,除了更新Nginx的缓存路由信息,还会把本upstream的后端server列表dump到本地,保持本地server信息与consul的一致性。
除了注册/注销后端的server到consul,会更新到Nginx的upstream路由信息外,对后端server属性的修改也会同步到nginx的upstream路由。
Upsync模块支持修改的属性有:weight、max_fails、fail_timeout、down。
- 修改server的权重可以动态的调整后端的流量。
- 若想要临时移除server,可以把server的down属性置为1。
- 若要恢复流量,可重新把down置为0。
每个work进程各自拉取、更新各自的路由表,采用这种方式的原因:
- 基于Nginx的进程模型,彼此间数据独立、互不干扰。
- 若采用共享内存,需要提前预分配,灵活性可能受限制,而且还需要读写锁,对性能可能存在潜在的影响。
- 若采用共享内存,进程间协调去拉取配置,会增加它的复杂性,拉取的稳定性也会受到影响。
Upsync模块高可用性
Nginx的后端列表更新依赖于Consul,但是不强依赖于它,具体表现为:
- 即使中途Consul意外挂了,也不会影响Nginx的服务,Nginx会沿用最后一次更新的服务列表继续提供服务。
- 若Consul重新启动提供服务,这个时候Nginx会继续去Consul探测,这个时候Consul的后端服务列表发生了变化,也会及时的更新到Nginx。
- work进程每次更新都会把后端列表dump到本地,目的是降低对Consul的依赖性,即使在consul不可用时,也可以Reload Nginx。
Nginx启动流程图如下:
Nginx启动时,master进程首先会解析本地的配置文件,解析完成功,接着进行一系列的初始化,之后便会开始work进程的初始化。work初始化时会去Consul拉取配置,进行work进程upstream路由信息的更新,若拉取成功,便直接更新,若拉取失败,便会打开配置的dump后端列表的文件,提取之前dump下来的server信息,进行upstream路由的更新,之后便开始正常的提供服务。
每次去拉取Consul都会设置连接超时,由于Consul在无更新的情况下默认会hang五分钟,所以响应超时配置时间应大于五分钟。大于五分钟之后,Consul依旧没有返回,便直接做超时处理。
Upsync模块安装
安装Consul
Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置。
Upsync最新版本是支持ectd,这里用ectd做为后端存储。有关consule的讲解后面单独来讲。如果你还没有etcd环境,可参考「etcd使用入门」一文搭建一个。
安装配置Nginx
- 下载对应软件包
这里使用的是Upsync最新版本,目前支持Nginx 1.9+。nginx-upstream-check-module
是Tengine中的模块,主要用于upstream的健康检查。由于nginx-upstream-check-module
最新版本只支持1.9.2,所以这里Nginx选用1.9.2。
| |
- 编译安装Nginx
| |
- 配置Nginx
Nginx会默认安装到/usr/local/nginx
目录下。
创建用户和相应目录
| |
修改Nginx主配置文件
| |
创建站点配置文件
| |
- 创建Nginx Systemd服务
| |
修改权限及加入开机启动
| |
现在可以使用下面的指令来管理Nginx服务。
| |
- 启动Nginx
| |
验证Nginx服务是否正常
| |
如果要单独查看Nginx服务日志,可以使用以下命令:
| |
验证Upsync模块
启动一个Web服务
这里在Nginx默认站点目录,用Python启动一个SimpleHTTPServer进行验证。
| |
后端存储增加数据
- 后端存储使用etcd
增加一个后端服务器
| |
其它Upstream模块中其它属性的默认值为:weight=1 max_fails=2 fail_timeout=10 down=0 backup=0;
。如果你要调整这些值,可以用以下命令格式进行提交:
| |
删除一个后端服务器
| |
- 后端存储使用Consul
增加一个后端服务器
| |
删除一个后端服务器
| |
测试站点是否正常访问
- 访问站点
页面自动根据proxy_pass http://test;
成功转到了后端服务器。
- 访问upstream列表
- 访问upstream状态
- 查看添加的后端服务是否被dump到本地
| |
参考文档
http://www.google.com
http://t.cn/Ra2WfSR
https://my.oschina.net/liucao/blog/470344
http://blog.csdn.net/yueguanghaidao/article/details/52801043
https://www.nginx.com/resources/wiki/start/topics/examples/systemd/
########################################################
基于 consul + upsync 的动态upstream管理
upsync介绍
upsync是微博开源的基于nginx的动态流量管理方案. github地址: https://github.com/weibocom/nginx-upsync-module.
nginx-upsync-module,它的功能是拉取 consul 的后端 server 的列表,并更新 Nginx 的路由信息。此模块不依赖于任何第三方模块。 consul 作为 Nginx 的 db,利用 consul 的 KV 服务,每个 Nginx work 进程独立的去拉取各个 upstream 的配置,并更新各自的路由。
upsync arch
consul简介
Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置. consul是分布式的, 高可用的, 可横向扩展的. 它具备以下特性:
-
服务发现: consul提供了通过DNS或者HTTP接口的方式来注册服务和发现服务. 一些外部的服务通过consul很容易的找到它所依赖的服务.
-
健康检测: consul的client提供了健康检查的机制, 可以通过用来避免流量被转发到有故障的服务上.
-
Key/Value存储: 应用程序可以根据自己的需要使用Consul提供的Key/Value存储. Consul提供了简单易用的HTTP接口, 结合其他工具可以实现动态配置, 功能标记, 领袖选举等等功能.
-
多数据中心: Consul支持开箱即用的多数据中心. 这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域.
consul架构
-
consul cluster由部署和运行了consul agent的节点组成. 在cluster中有两种角色: server 和 client.
-
server 和 client 的角色和consul cluster上运行的应用服务无关, 是基于consul层面的一种角色划分.
-
consul server: 用于维护consul cluster的状态信息. 官方文档中给出的建议是: 至少要运行3个或者3个以上的consul server. 多个server之中需要选举一个leader, 这个选举过程consul基于raft协议实现. 多个server节点上的consul数据信息保持强一致性.
-
consul client: 只维护自身的状态, 并上报请求给server.
consul arch
consul的安装和启动
-
consul的安装比较简单, 可参考官方文档: https://www.consul.io/intro/getting-started/install.html
-
启动consul集群
启动两台consul server:
consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -client 0.0.0.0 -bind=192.168.100.123 -ui-dir /root/consul_ui -node=server01 -dc=upstream
consul agent -server -data-dir /tmp/consul -client 0.0.0.0 -bind=192.168.100.125 -node=server02 -dc=upstream
一台 consul client:
consul agent -data-dir /tmp/consul -client 0.0.0.0 -bind=192.168.100.127 -node=client01 -dc=upstream
- 查看集群成员:
[root@ruby-100-123 ~]# consul members
Node Address Status Type Build Protocol DC
client01 192.168.100.127:8301 alive client 0.7.3 2 upstream
server01 192.168.100.123:8301 alive server 0.7.3 2 upstream
server02 192.168.100.125:8301 alive server 0.7.3 2 upstream
通过以上命令可以查看集群中的地址信息, 健康状态, 启动的角色, 版本信息等.
如果需要查看一些元数据的话, 可以通过加 -detailed 参数查看:
[root@ruby-100-123 ~]# consul members --detailed
Node Address Status Tags
client01 192.168.100.127:8301 alive build=0.7.3:'a90bb8f,dc=upstream,id=64ff71ab-465d-1d7e-22f6-9df6860c0293,role=node,vsn=2,vsn_max=3,vsn_min=2
server01 192.168.100.123:8301 alive bootstrap=1,build=0.7.3:'a90bb8f,dc=upstream,id=7e1a3bed-2474-898f-275b-212d5fb8f646,port=8300,role=consul,vsn=2,vsn_max=3,vsn_min=2
server02 192.168.100.125:8301 alive build=0.7.3:'a90bb8f,dc=upstream,id=ad7549e5-b1b6-7d52-a04f-1efd4e0fd58a,port=8300,role=consul,vsn=2,vsn_max=3,vsn_min=2
服务注册
服务注册有两种方式: 通过服务定义配置文件 和 通过HTTP接口. consul推荐使用第一种配置方式.
mkdir /etc/consul.d
echo '{"service": {"name": "web", "tags": ["rails"], "port": 80}}' >/etc/consul.d/web.json
consul agent -server -data-dir /tmp/consul -client 0.0.0.0 -bind=192.168.100.125 -node=server02 -dc=upstream -config-dir /etc/consul.d/
然后我们可以通过HTTP接口查询注册的服务:
-bash: Python: command not found
[root@ruby-2-1-source ~]# curl -s http://localhost:8500/v1/catalog/service/web | python -m json.tool
[
{
"Address": "192.168.100.125",
"CreateIndex": 186121,
"ID": "ad7549e5-b1b6-7d52-a04f-1efd4e0fd58a",
"ModifyIndex": 186121,
"Node": "server02",
"NodeMeta": {},
"ServiceAddress": "",
"ServiceEnableTagOverride": false,
"ServiceID": "web",
"ServiceName": "web",
"ServicePort": 80,
"ServiceTags": [
"rails"
],
"TaggedAddresses": {
"lan": "192.168.100.125",
"wan": "192.168.100.125"
}
}
]
健康监测
同样地, 我们可以通过定义配置文件 或 HTTP接口来定义健康监测.
我们定义一个简单的ping检查, 每隔30s一次, 然后重新启动client.
echo '{"check": {"name": "ping", "script": "ping -c1 www.zhe800.com >/dev/null", "interval": "30s"}}' >/etc/consul.d/ping.json
consul agent -server -data-dir /tmp/consul -client 0.0.0.0 -bind=192.168.100.125 -node=server02 -dc=upstream -config-dir /etc/consul.d/
定义完健康监测的配置之后, 我们可以通过HTTP接口来检查各个agent的运行状态.
curl -s http://localhost:8500/v1/health/state/any | python -m json.tool
Key/Value存储
consul 提供了一个简单易用的Key/Value存储系统, 并提供了相关的HTTP接口, 可以用来动态获取配置(我们的动态upstream项目就是这种应用)、进行服务协调、主节点选举等.
可以通过HTTP接口查看K/V系统中存储了哪些内容:
curl -v http://127.0.0.1:8500/v1/kv/?recurse
通过HTTP接口往K/V系统写入数据:
curl -X PUT -d 'test' http://127.0.0.1:8500/v1/kv/key1/
curl -X PUT -d 'test' http://127.0.0.1:8500/v1/kv/key1/key2?param1=test
curl -X PUT -d 'test' http://127.0.0.1:8500/v1/kv/key1/key2/key3
写入数据之后, 可以通过上面的命令查看. 其value采用Base64加密.
另外, 也可以查看某个单个的key:
curl -s http://127.0.0.1:8500/v1/kv/key1 |python -m json.tool
WEB界面
URL: http://192.168.100.123:8500/ui
启动命令需要增加: -ui-dir 参数, 用于指前端相关的文件位置.
动态upsteams管理系统
动态upsteams管理系统
结合zhe800自身的业务来说:
- 降低运维配置的复杂度:
原本的配置方式:
upstream test {
server 127.0.0.1:9601 weight=40 max_fails=10 fail_timeout=30s;
server 127.0.0.1:9602 weight=20 max_fails=10 fail_timeout=30s;
server 127.0.0.1:9603 weight=5 max_fails=10 fail_timeout=30s;
server 127.0.0.1:9604 weight=20 max_fails=10 fail_timeout=30s;
server 127.0.0.1:9605 weight=10 max_fails=10 fail_timeout=30s;
server 127.0.0.1:9606 weight=20 max_fails=10 fail_timeout=30s;
keepalive 166;
}
使用 upsync 之后的配置方式:
upstream test {
server 127.0.0.1:11111;
upsync 192.168.100.123:8500/v1/kv/upstreams/test upsync_timeout=6m upsync_interval=500ms upsync_type=consul strong_dependency=off;
upsync_dump_path /usr/local/nginx/conf/servers/servers_test.conf;
}
- 便于动态扩容缩容
运维可以很方便的在后台增删服务器
- 基于upstreams后台提供的服务器列表信息, 结合ads可以实现上线更新时的无缝切换
系统提供了每个upstream对应的服务列表的API, 以及启动, 关闭相关服务的API. ads系统更新上线的时候, 通过调用相关的API, 完成无缝上线.
链接:
https://www.jianshu.com/p/35b03c82f9fd
https://blog.csdn.net/shenshouer/article/details/52925735