Nginx+Consul+UpSync动态配置负载均衡(二)
- 一、安装nginx模块
- 1.合并module
- 2.重新编译nginx
- 二、添加stream配置文件
- 1.添加stream模块
- 2.创建stream配置文件
- 3.创建持久化文件目录
- 4.启动nginx
- 三、模拟tcp服务端
- 1.创建tcp服务器
- 2.给每个服务做区分
- 四、开启并验证tcp的动态负载均衡
- 1.启动Consul服务
- 2.添加服务端信息到consul
- 3.验证动态负载均衡是否成功
- 五、问题记录
- 1. upsync_del_peer: upstream "app" cannot delete all peers
- 2. upsync_check_key: has no port in /
环境说明
主机名 | 系统版本 | ip地址 | nginx version | consul version | upsync version | 备注 |
master | centos-release-7-7.1908.0.el7.centos.x86_64 | 192.168.137.252 | nginx-1.17.5 | consul_1.6.1_linux_amd64 | nginx-upsync-module |
上一篇我们使用Consul+UpSync的方案给ngxin加上了动态负载均衡的功能,但是他只能作为http模块中的负载均衡,也就是只能代理http协议。这篇,在之前的基础上,我们加强一下,添加一个支持stream模块的动态负载均衡功能,让nginx支持tcp/udp的动态负载。顺便也温习一下其他知识点。
一、安装nginx模块
之前我们已经下载过nginx-upsync-module
模块了,但是这个模块不支持在stream{}模块中使用,而nginx-stream-upsync-module
模块是为stream{}提供支持的。我们需要同时安装这两个module模块。但是想要同时使用这两个模块的话,是不能同时在编译nginx的时候把这两个模块一起编译进去的。所以我们需要先将两个模块合并成一个。
1.合并module
[root@master02 ~]# cd /opt/nginx/
[root@master02 nginx]# git clone https://github.com/CallMeFoxie/nginx-upsync.git
原文章是将3个资源包下载好之后再进行复制的,但是他那里写的复制命令是有问题的,不能复制子目录,请注意。
我们这里直接进行下载覆盖即可。
[root@master02 nginx]# cd /opt/nginx/nginx-upsync
[root@master02 nginx-upsync]# git clone https://github.com/weibocom/nginx-upsync-module.git
[root@master02 nginx-upsync]# git clone https://github.com/xiaokai-wang/nginx-stream-upsync-module.git
这样我们就将nginx-upsync-module
跟nginx-stream-upsync-module
两个模块合并成了nginx-upsync
模块了。
2.重新编译nginx
之前我们已经编译过一次nginx了,但是当时只将nginx-upsync-module
模块编译进去,现在我们需要用nginx-upsync
模块进行替换,所以要重新编译。
2.1 编译安装nginx
[root@master02 nginx-upsync]# cd /opt/nginx/nginx-1.17.5
[root@master02 nginx-1.17.5]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_flv_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_realip_module --with-pcre --add-module=/opt/nginx/nginx-upsync --with-stream
注意最后两个参数--add-module=/opt/nginx/nginx-upsync --with-stream
,第一个参数我们将之前的nginx-upsync-module
替换成了nginx-upsync
,第二个参数--with-stream
是开启nginx的stream模块。
[root@master02 nginx-1.17.5]# make
[root@master02 nginx-1.17.5]# /usr/local/nginx/sbin/nginx -s stop
[root@master02 nginx-1.17.5]# \cp /opt/nginx/nginx-1.17.5/objs/nginx /usr/local/nginx/sbin/
第一条命令是安装,不要使用make install
命令,这个命令可能会覆盖之前的nginx工作目录。
第二条命令是停止运行中的nginx,因为接下来我们要替换旧的nginx执行文件。
第三条是用刚刚编译安装成功的nginx替换旧的nginx执行文件。\cp
命令的作用是若文件存在不询问直接覆盖。
我们可以使用-V
命令来查看nginx的编译参数:
[root@master02 nginx-1.17.5]# /usr/local/nginx/sbin/nginx -V
可以看到是我们刚刚的编译参数。
二、添加stream配置文件
1.添加stream模块
[root@master02 nginx-1.17.5]# cd /usr/local/nginx/conf
[root@master02 conf]# vim nginx.conf
在文件中添加如下代码块,stream模块与http模块并列。
stream {
#加载外部配置文件
include /usr/local/nginx/conf.d/stream/*.conf;
}
2.创建stream配置文件
[root@master02 conf]# mkdir /usr/local/nginx/conf.d/stream
[root@master02 conf]# cd /usr/local/nginx/conf.d/stream
[root@master02 stream]# vim stream-mysql-3307.conf
因为mysql通常是用tcp连接的,所以我们使用mysql来做测试。故文件名中有mysql。
文件中填入下面代码:
upstream mysql {
server 127.0.0.1:11111;
upsync 192.168.137.252:8500/v1/kv/upstreams/stream/ upsync_timeout=6m upsync_interval=500ms upsync_type=consul strong_dependency=off;
upsync_dump_path /usr/local/nginx/conf/servers/servers_stream.conf;
include /usr/local/nginx/conf/servers/servers_stream.conf;
}
server {
listen 3307;
proxy_pass mysql;
}
3.创建持久化文件目录
[root@master02 stream]# vim /usr/local/nginx/conf/servers/servers_stream.conf
直接空文件退出即可。
4.启动nginx
[root@master02 stream]# /usr/local/nginx/sbin/nginx -t
[root@master02 stream]# /usr/local/nginx/sbin/nginx
三、模拟tcp服务端
1.创建tcp服务器
我们需要几个tcp的服务端来验证我们的动态负载是否可用。
我这边是使用docker,在docker中创建了3个mysql的容器:
如果没有其他更好的方式,也可以采取我这种。我这个mysql是装在另外一台机子192.168.137.123
上面。
2.给每个服务做区分
分别登录3个数据库服务端,我们在每个数据库服务端中都创建一个叫test
的数据库实例,然后分别在每个数据库实例中创建一张表,我们可以创建不同的表名来做为三台服务器之间的区分。当然也可以表名相同,然后利用表中数据不同来做区分。我这里使用表名区分,更加简单、直观。
四、开启并验证tcp的动态负载均衡
1.启动Consul服务
如果之前启动的没有关闭就可以不用再启动了。
[root@master02 stream]# /opt/nginx/consul agent -dev -ui -node=consul-dev -client=192.168.137.252
2.添加服务端信息到consul
我们依次将3个mysql服务端的地址添加到consul
[root@master02 stream]# curl -X PUT http://192.168.137.252:8500/v1/kv/upstreams/tcp/192.168.137.123:3301
[root@master02 stream]# curl -X PUT http://192.168.137.252:8500/v1/kv/upstreams/tcp/192.168.137.123:3302
[root@master02 stream]# curl -X PUT http://192.168.137.252:8500/v1/kv/upstreams/tcp/192.168.137.123:3303
此时我们可以查看一下持久化文件中的内容
[root@master02 stream]# cat /usr/local/nginx/conf/servers/servers_tcp.conf
如果是我们刚刚添加的三个服务端列表的话,就是成功了。
3.验证动态负载均衡是否成功
我们在之前的navicat软件中新建一个连接。
连接至我们之前配置的192.168.137.252:3307
。
先点击测试连接,如果不成功的话,需要先找下原因。我这边是没问题的。
我们打开刚刚创建的连接,进入表选项中,可以看到一个表名称,我现在看到的是t_lb2
这张表。
然后我们将连接先关闭,然后再重新连接,看看表有没有变化。可以看到我这里已经变成t_lb1
表了
重复几次关闭连接再重新连接,看看表的变化,会发现表名称会在t_lb1
/t_lb2
/t_lb3
三张表中随机出现,这刚刚好对应到我们一开始在mysql的三个服务端中分别创建的3张表。由此也就可以说明我们的tcp动态负载均衡已经成功了。
如果还不太确信的话,可以使用命令删除两个负载均衡服务,只留下一个,再次验证一下lb-upstream-mysql
中表的名称是不是不会变化了。
[root@master02 stream]# curl -X DELETE http://127.0.0.1:8500/v1/kv/upstreams/tcp/192.168.137.123:3302
[root@master02 stream]# curl -X DELETE http://127.0.0.1:8500/v1/kv/upstreams/tcp/192.168.137.123:3303
这个时候,再去尝试重新连接lb-upstream-mysql
,发现不管重连多少次,表中只会出现t_lb1
这个表名称。
这样就可以完全确定我们已经配置好了。
五、问题记录
1. upsync_del_peer: upstream “app” cannot delete all peers
当nginx重启,consul后台与持久化文件中的服务器列表不统一时,nginx日志中将会报错:
upsync_del_peer: upstream "app" cannot delete all peers
upsync_process: upstream del peers failed
但是这个时候负载均衡还是依然可以访问的,只是持久化文件写入失败了。consul服务正常启用的时候,负载均衡列表以consul服务中的列表为准。
如果我们想要持久化文件被写入,就要在nginx重启之前,将持久化文件内的服务器列表手动配置成跟consul后台一致,然后再重启nginx。这样问题就得以解决了。
2. upsync_check_key: has no port in /
nginx中会一直报这个错upsync_check_key: has no port in /
,原因是consul在添加键值的时候,默认会把我们添加的文件夹也当成一个键值对,而文件夹这个key是没有带端口的。所以nginx会报这个错。
但是nginx可以正常使用的。这个错误,暂时我也不知道怎么解决。
参考连接:https://github.com/CallMeFoxie/nginx-upsynchttps://github.com/xiaokai-wang/nginx-stream-upsync-module