Cloud Native 5 min read

How to Auto‑Update Nginx Upstreams with Nacos Service Discovery (Lua & Java Agents)

Learn how to replace manual Nginx upstream configuration with automatic service discovery using Nacos, by either writing Lua scripts with the nginx‑lua‑module or building a Java/Golang agent that fetches instance lists via the Nacos API, updates upstream blocks, and triggers hot reloads.

Java Architecture Diary
Java Architecture Diary
Java Architecture Diary
How to Auto‑Update Nginx Upstreams with Nacos Service Discovery (Lua & Java Agents)

Background

Traditionally, Nginx load‑balancing is configured manually by defining an

upstream

block with static server IP:PORT entries and reloading Nginx whenever the service list changes.

<code>upstream serverList {
    server 172.17.0.111:9999;
    server 172.17.0.110:9999;
}
server {
   location / {
       proxy_pass http://serverList;
   }
}
</code>

In a micro‑service architecture, instances are registered in a service registry such as Nacos or Eureka, which already maintains the IP:PORT list. The goal is to let Nginx obtain this list automatically and update its

upstream

definition with hot reload.

Two Implementation Approaches

Use the

nginx‑lua‑module

to write a Lua script that calls the registry’s HTTP API, generates the

upstream

configuration, and triggers a timed

reload

for hot updates.

Write a separate agent in Java or Golang that uses the Nacos SDK to subscribe to service changes, generates the

upstream

block, and invokes

nginx -s reload

when instances appear or disappear.

nacos‑nginx‑template

The second approach is packaged as the

nacos‑nginx‑template

project, which runs an agent that watches Nacos and rewrites Nginx configuration.

Download binary

Configure config.toml

The configuration file uses TOML syntax. Example:

<code>nginx_cmd = "/usr/sbin/nginx"  # full path to nginx binary
nacos_addr = "172.16.0.100:8848" # Nacos address
reload_interval = 1000          # refresh interval in ms

[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"
</code>

Start the agent

<code>sh bin/startup.sh</code>

Core Java Code

Read

config.toml

, subscribe to Nacos services, and refresh upstream blocks.

<code>for (DiscoverConfigBO configBO : list) {
    namingService.subscribe(configBO.getServiceName(),
            event -> {
                List<Instance> instances = namingService.getAllInstances(configBO.getServiceName());
                // update nginx upstream
                refreshUpstream(instances, configBO.getUpstream(), configBO.getConfigPath());
            });
}
</code>
<code>private boolean refreshUpstream(List<Instance> instances, String nginxUpstream, String nginxConfigPath) {
    Pattern pattern = Pattern.compile(UPSTREAM_REG.replace(PLACEHOLDER, nginxUpstream));
    String conf = FileUtl.readStr(nginxConfigPath);
    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());
    conf = matcher.replaceAll(newUpstream);
    return true;
}
</code>

Reload Nginx from Java:

<code>Runtime.getRuntime().exec("nginx -s reload");</code>
Javaservice discoveryNacosnginxLuadynamic upstream
Java Architecture Diary
Written by

Java Architecture Diary

Committed to sharing original, high‑quality technical articles; no fluff or promotional content.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.