![](/style/images/good.png)
![](/style/images/bad.png)
通过Nacos让Nginx拥有服务发现能力
source link: https://segmentfault.com/a/1190000021686433
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
背景
先来回忆一下, nginx
如何配置多个实例的负载均衡,配置如下:
upstream serverList { server 172.17.0.111:9999; server 172.17.0.110:9999; } server { location / { proxy_pass http://serverList; } }
当我们的服务实例变化时,要手动修改 nginx.conf
然后 nginx -s reload
。
在微服务架构下,我们的服务均已经注册到 注册中心 例如(nacos/eureka),注册中心已经维护所有服务实例的 IP:PORT
列表 ,为何不直接通过 nginx 来获取注册中心中的 IP:PORT
列表自动配置 upstream
和热更新。
如上思路实现有如下:
- 使用
nginx-lua-module
模块编写lua
脚本, 调用注册中心的Http API
来获取实例列表 配置upstream
,定时reload
热更新 - 使用
JAVA/Golang
编写单独的agent
,直接使用nacos 对应语言的 SDK ,获取实例列表生成upstream
,并且使用Naocs SDK
监听服务变化reload
nacos-nginx-template 使用
nacos-nginx-template 以上的第二种思路实现以Agent的形式让Nginx实现对Nacos的服务发现。
-
下载二进制包
点击此处下载: 最新稳定版
-
配置config.toml
配置文件使用 TOML 进行配置
nacos_addr = "172.16.0.100:8848" #nacos 服务地址
reload_interval = 1000 # 刷新间隔
[discover_config1]
nginx_config = "/etc/nginx/nginx.conf" #nginx config 配置
nginx_upstream = "upsteam1" #upstream 名称
nacos_service_name = "service1" #nacos 服务名称
[discover_config2]
nginx_config = "/etc/nginx/nginx.conf"
nginx_upstream = "upsteam2"
nacos_service_name = "service2"
3. #### 启动,即可使用
sh bin/startup.sh
## 核心代码 - 获取 `config.toml` 配置的信息,支持多个 `upstream` ,调用Nacos Api 拉取实例列表
for (DiscoverConfigBO configBO : list) {
namingService.subscribe(configBO.getServiceName(), event -> { List<Instance> instances = namingService .getAllInstances(configBO.getServiceName()); //更新nginx中的upstream refreshUpstream(instances, configBO.getUpstream(), configBO.getConfigPath()); } );
}
- 根据实例列表,拼凑 `upstream`
private boolean refreshUpstream(List<Instance> instances, String nginxUpstream, String nginxConfigPath) { //获取到upstream 名称 Pattern pattern = Pattern.compile(UPSTREAM_REG.replace(PLACEHOLDER, nginxUpstream)); //获取到配置文件内容 String conf = FileUtl.readStr(nginxConfigPath); //拼接新的upstream String newUpstream = UPSTREAM_FOMAT.replace(PLACEHOLDER, nginxUpstream); StringBuffer servers = new StringBuffer(); if (instances.size() > 0) { for (Instance instance : instances) { //不健康或不可用的跳过 if (!instance.isHealthy() || !instance.isEnabled()) { continue; } servers.append(formatSymbol + " server " + instance.getIp() + ":" + instance.getPort() + ";\n"); } } servers.append(formatSymbol); newUpstream = newUpstream.replace(PLACEHOLDER_SERVER, servers.toString()); //替换原有的upstream conf = matcher.replaceAll(newUpstream); return true; }
- Java 调用nginx reload
Runtime.getRuntime().exec("nginx -s reload");
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK