通过Nginx、Consul、Upsync实现动态负载均衡和服务平滑发布

前段时间顺利地把整个服务集群和中间件全部从UCloud迁移到阿里云,笔者担任了架构和半个运维的角色。这里详细记录一下通过NginxConsul、Upsync实现动态负载均衡和服务平滑发布的核心知识点和操作步骤,整个体系已经在生产环境中平稳运行。编写本文使用的虚拟机系统为CentOS7.x,虚拟机的内网IP为192.168.56.200。

通过Nginx、Consul、Upsync实现动态负载均衡和服务平滑发布

动态负载均衡的基本原理

一般会通过upstream配置Nginx的反向代理池:

http { upstream upstream_server{ server 127.0.0.1:8081; server 127.0.0.1:8082; } server { listen 80; server_name localhost; location / { proxy_pass ; } } }

现在假如8081端口的服务实例挂了需要剔除,那么需要修改upstream为:

upstream upstream_server{ # 添加down标记该端口的服务实例不参与负载 server 127.0.0.1:8081 down; server 127.0.0.1:8082; }

并且通过nginx -s reload重新加载配置,该upstream配置才会生效。我们知道,服务发布时候重启过程中是处于不可用状态,正确的服务发布过程应该是:

把该服务从对应的upstream剔除,一般是置为down,告知Nginx服务upstream配置变更,需要通过nginx -s reload进行重载。

服务构建、部署和重启。

通过探活脚本感知服务对应的端口能够访问,把该服务从对应的upstream中拉起,一般是把down去掉,告知Nginx服务upstream配置变更,需要通过nginx -s reload进行重载。

上面的步骤一则涉及到upstream配置,二则需要Nginx重新加载配置(nginx -s reload),显得比较笨重,在高负载的情况下重新启动Nginx并重新加载配置会进一步增加系统的负载并可能暂时降低性能。

所以,可以考虑使用分布式缓存把upstream配置存放在缓存服务中,然后Nginx直接从这个缓存服务中读取upstream的配置,这样如果有upstream的配置变更就可以直接修改缓存服务中对应的属性,而Nginx服务也不需要reload。在实战中,这里提到的缓存服务就选用了Consul,Nginx读取缓存中的配置属性选用了新浪微博提供的Nginx的C语言模块nginx-upsync-module。示意图大致如下:

通过Nginx、Consul、Upsync实现动态负载均衡和服务平滑发布

Consul安装和集群搭建

Consul是Hashicorp公司的一个使用Golang开发的开源项目,它是一个用于服务发现和配置的工具,具备分布式和高度可用特性,并且具有极高的可伸缩性。Consul主要提供下面的功能:

服务发现。

运行状况检查。

服务分块/服务网格(Service Segmentation/Service Mesh)。

密钥/值存储。

多数据中心。

下面是安装过程:

mkdir /data/consul cd /data/consul wget https://releases.hashicorp.com/consul/1.7.3/consul_1.7.3_linux_amd64.zip # 注意解压后只有一个consul执行文件 unzip consul_1.7.3_linux_amd64.zip

解压完成后,使用命令nohup /data/consul/consul agent -server -data-dir=http://www.likecs.com/tmp/consul -bootstrap -ui -advertise=192.168.56.200 -client=192.168.56.200 > /dev/null 2>&1 &即可后台启动单机的Consul服务。启动Consul实例后,访问:8500/即可打开其后台管理UI:

通过Nginx、Consul、Upsync实现动态负载均衡和服务平滑发布

下面基于单台虚拟机搭建一个伪集群,关于集群的一些配置属性的含义和命令参数的解释暂时不进行展开

# 创建集群数据目录 mkdir /data/consul/node1 /data/consul/node2 /data/consul/node3 # 创建集群日志目录 mkdir /data/consul/node1/logs /data/consul/node2/logs /data/consul/node3/logs

在/data/consul/node1目录添加consul_conf.json文件,内容如下:

{ "datacenter": "es8-dc", "data_dir": "/data/consul/node1", "log_file": "/data/consul/node1/consul.log", "log_level": "INFO", "server": true, "node_name": "node1", "ui": true, "bind_addr": "192.168.56.200", "client_addr": "192.168.56.200", "advertise_addr": "192.168.56.200", "bootstrap_expect": 3, "ports":{ "http": 8510, "dns": 8610, "server": 8310, "serf_lan": 8311, "serf_wan": 8312 } }

在/data/consul/node2目录添加consul_conf.json文件,内容如下:

{ "datacenter": "es8-dc", "data_dir": "/data/consul/node2", "log_file": "/data/consul/node2/consul.log", "log_level": "INFO", "server": true, "node_name": "node2", "ui": true, "bind_addr": "192.168.56.200", "client_addr": "192.168.56.200", "advertise_addr": "192.168.56.200", "bootstrap_expect": 3, "ports":{ "http": 8520, "dns": 8620, "server": 8320, "serf_lan": 8321, "serf_wan": 8322 } }

在/data/consul/node3目录添加consul_conf.json文件,内容如下:

{ "datacenter": "es8-dc", "data_dir": "/data/consul/node3", "log_file": "/data/consul/node3/consul.log", "log_level": "INFO", "server": true, "node_name": "node3", "ui": true, "bind_addr": "192.168.56.200", "client_addr": "192.168.56.200", "advertise_addr": "192.168.56.200", "bootstrap_expect": 3, "ports":{ "http": 8530, "dns": 8630, "server": 8330, "serf_lan": 8331, "serf_wan": 8332 } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjjwx.html