您现在的位置是:首页 > 文章详情

通过Nacos让Nginx拥有服务发现能力

日期:2020-02-04点击:442

背景

先来回忆一下, 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的服务发现。

  1. 下载二进制包

点击此处下载:最新稳定版

  1. 配置config.toml

配置文件使用TOML进行配置

nginx_cmd = "/usr/sbin/nginx" nacos_addr = "172.16.0.100:8848,172.16.0.101:8848,172.16.0.102:8848" reload_interval = 1000 [discover_config1] nginx_config = "/etc/nginx/nginx.conf" nginx_upstream = "upsteam1" nacos_service_name = "service1" [discover_config2] nginx_config = "/etc/nginx/nginx.conf" nginx_upstream = "upsteam2" nacos_service_name = "service2"
参数 描述 例子
nginx_cmd nginx命令的全路径 "/usr/sbin/nginx"
nacos_addr nacos的地址 "172.16.0.100:8848,172.16.0.101:8848,172.16.0.102:8848"
reload_interval nginx reload命令执行间隔时间(ms 默认值1000) 1000
nacos_service_name nacos服务名 "com.nacos.service.impl.NacosService"
nginx_config 需要修改nginx配置的路径 "/etc/nginx/nginx.conf"
nginx_upstream nginx中upstream的名字 "nacos-service"
  1. 启动,即可使用

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");
原文链接:https://yq.aliyun.com/articles/743647
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章