先来回忆一下, 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 以上的第二种思路实现以Agent的形式让Nginx实现对Nacos的服务发现。
点击此处下载:最新稳定版
配置文件使用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"
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");
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。