本系列第一章节我们就知道了如何配置upstream。下面要学习的是如何不写死服务列表,而是通过服务注册、发现的方式来实现upstream列表的动态变更。书中是使用Consul来实现的,它是一款开源的分布式服务注册与发现系统。简单来说,其核心思想就是,upstream服务向Consul注册服务,Nginx能监听到Consul上注册的服务变更,然后修改upstream列表,最后重启Nginx。本人也没有使用过该产品,就一起来学习下吧。
了解Consul
首先得稍微了解下Consul,要不然玩儿不起来。
- 安装。本人直接使用
brew install consul
,如果是其他系统,可以去官网下载对应的安装包。 - 启动。浏览了下官网,感觉跟Zookeeper有点像。通过命令
consul agent -dev
启动,如果能正常打印出日志,表示安装成功了。这里就不研究Consul,有兴趣的同学自行去官网看文档。 - Web UI。Consul自带Web UI,而且-dev模式下是默认启动的,访问
localhost:8500/ui
即可。
注册服务
将服务注册到Consul。和Consul的交互可以使用HTTP协议,发送如下请求可以注册一个服务到Consul:
成功之后登录控制台,会看到SERVICES下多出了一个real_server服务:
书中注册服务是请求的catalog API,但是注册完之后过会儿会被自动deregister,查了下文档,换成上述API了。另外,有一点和zookeeper不太一样的是,停止Consul后,之前注册的服务就消失了。不知道和目前测试用的是单节点有没关系,如果线上准备使用该工具,还得详细地看完文档再说。解释下上述API的几个参数:
- ID:代表要注册的服务的唯一标识
- Name:表示一组服务的名称
- Tags:服务标签,可以用于区分开发、测试环境
- Address:服务的地址
- Port:服务的端口
还有一个real_server_2也要注册上去,改下参数ID和Port就行了,就不贴出来了。
Consul-template
Consul-template的作用是生成upstream的配置模板。这个不包含在consul中,是单独的工具,先安装brew install consul-template
。接下来在conf目录下新建real_server.ctmpl文件,内容如下:
大概可以看出是遍历数据中心dc1中的Tags为dev,Name为real_server的服务。Consul启动的时候打印日志有一行Datacenter: 'dc1'
,这个就是数据中心。其余的占位符都对应注册服务发送的API请求参数。
还需要再新建一个Nginx重启脚本,同样再conf目录下新建restart.sh,并且给该文件执行权限:
最后在修改ngxin.conf,删除原来的upstream配置,通过includ引入配置文件
Consul-template配置完毕,先不启动,还差一步。对了,有一点先注意下,我们新建的模板是real_server.ctmpl,而nginx.conf中include的文件是real_server.conf。
Java服务
在项目中引入Consul Java Client可以实现服务的注册与摘除,那上面直接通过HTTP的注册方式就当了解下了。下面贴出核心代码:
启动项目,然后登到Consul Web界面看一下,服务是否注册成功。另外,不要忘了把代码拷到real_server_2中,port和serviceId是取的配置文件中的值,所以不用改啥。另外,如果是真实环境的话serviceId可以取成ip地址+端口号,这样同一个应用的serviceId自然就不一样了。
测试
在整体测试之前,我们还不知道consul-template怎么用。下面就利用consul、real_server.ctmpl和Java服务,来先了测试下consul-template。
- 启动Consul:
consul agent -dev
- real_server_1、real_server_2
- 在terminal中执行如下命令:123consul-template -consul-addr 127.0.0.1:8500 -template \"/Users/zhangjing/IdeaProjects/hunger/conf/real_server.ctmpl:\/Users/zhangjing/IdeaProjects/hunger/conf/real_server.conf"
成功之后会发现多了一个文件real_server.conf,其内容为:
其过程就是consul-template会监听指定的consul(-consul-addr指定的地址),监听的内容在real_server.ctmpl中定义。一旦相关内容有改动(此处指的是注册在consul上的服务),就会把更改后的内容输出到指定文件(此处是real_server.conf)。这里-template参数的格式为”模板源文件:将要写入的目标文件”。如果停掉其中一个服务,real_server.conf的内容会即时更新。可见达到实时更改配置的效果了。
有一点需要说明一下,consul-template是触发执行的,也就说监听的内容有改动才会触发命令。所以,有可能当时执行consul-template命令的时候什么事都不会发生,会误以为命令没有生效。这一点困扰了我一会儿,所以就提一下。
至此,相关知识点已经梳理完毕,下面整合起来测试下,列出测试步骤:
- 启动Consul:
consul agent -dev
启动consul-template
1234consul-template -consul-addr 127.0.0.1:8500 -template \"/Users/zhangjing/IdeaProjects/hunger/conf/real_server.ctmpl:\/Users/zhangjing/IdeaProjects/hunger/conf/real_server.conf:\sh /Users/zhangjing/IdeaProjects/hunger/conf/restart.sh"这里的命令稍有不同,在-template参数中加入了执行脚本
启动real_server_1、real_server_2,从输出可以看出nginx先被启动,然后又重启了:
1234nginx start0 52600 1 0 5:36下午 ?? 0:00.00 nginx: master ...-2 52601 52600 0 5:36下午 ?? 0:00.00 nginx: worker processngixn restart请求Nginx:
123456curl localhostfrom real server 1%curl localhostfrom real server 2%...可以自行停止、启动real_server进行测试
这种实现方式会导致每次发现配置有变更,都需要reload nginx。书中还有另外一种方式,通过lua脚本的配合来实现无reload动态负载均衡,有兴趣的同学可以自行去看,本章节内容就到这里了。