задний план
Давайте сначала вспомним,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
list, почему бы не получить данные в реестре напрямую через nginxIP:PORT
Автоматическая настройка спискаupstream
и горячие обновления. Вышеуказанные идеи реализуются следующим образом:
- использовать
nginx-lua-module
написание модуляlua
скрипт, который вызывает реестрHttp API
чтобы получить список экземпляров configureupstream
, времяreload
Горячее обновление - использовать
JAVA/Golang
написать отдельныйagent
, напрямую используйте SDK соответствующего языка nacos, чтобы получить список экземпляров для созданияupstream
и использоватьNaocs SDK
Следите за изменениями в сервисеreload
использование шаблона nacos-nginx
nacos-nginx-templateВторая вышеприведенная идея реализует обнаружение службы Nacos с помощью Nginx в виде агента.
-
Скачать бинарный пакет
Нажмите сюда для того, чтобы скачать:Последняя стабильная версия
-
настроить config.toml
использование конфигурационного файлаTOMLнастроить
nginx_cmd = "/usr/sbin/nginx" #nginx命令的全路径
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"
-
старт, готов к использованию
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
Runtime.getRuntime().exec("nginx -s reload");