You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NGINX与Docker原生DNS实现API负载均衡的轮询失效问题

解决NGINX + Docker DNS负载均衡仅转发到单服务器的问题

我来帮你搞定这个头疼的问题——这种情况我碰过好多次,核心原因其实是NGINX默认的DNS缓存机制在搞鬼!咱们一步步拆解解决:

为什么会只转发到单服务器?

Docker的原生DNS(比如你配置的servers.api别名)确实会返回所有在线API容器的IP,但NGINX默认是启动时一次性解析域名,之后就把结果缓存起来再也不更新。哪怕后面有新的API容器上线,或者现有容器重启换了IP,NGINX都不会主动去重新查询,自然只会死死盯着第一次解析到的那台服务器。

解决方案:让NGINX动态解析Docker DNS

1. 修改NGINX配置,强制动态解析

把你的nginx.conf改成下面这样,重点是添加解析器配置和用变量存储后端地址:

worker_processes 2;
events {
    worker_connections 1024;
}
http {
    sendfile on;
    # 指定Docker内置DNS服务器,30秒刷新一次解析结果
    resolver 127.0.0.11 valid=30s;
    resolver_timeout 5s;

    # 可选:添加日志记录后端IP,方便验证负载均衡
    log_format proxy_log '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$upstream_addr"';
    access_log /var/log/nginx/access.log proxy_log;

    server {
        listen 8080;
        location / {
            # 用变量存后端域名,让NGINX每次请求都重新解析
            set $api_backend servers.api;
            proxy_pass http://$api_backend;
            
            # 常规代理配置,保证请求头正确传递
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

这里的关键细节:

  • 127.0.0.11是Docker固定内置的DNS服务器地址,所有容器都能直接访问
  • valid=30s告诉NGINX每30秒重新查询一次域名,确保能获取到最新的API容器IP列表
  • 用set $api_backend变量存储后端域名,NGINX遇到变量形式的proxy_pass时,就不会在启动时缓存解析结果,而是每次请求都重新解析,这样就能拿到所有IP实现轮询

2. 优化Docker Compose配置(更规范的做法)

现在Docker Compose已经不推荐用links了,换成自定义网络更稳定,服务之间直接用服务名就能互通:

version: '3.8'
networks:
  api-internal:
    driver: bridge

services:
  proxy:
    restart: always
    build: ./src/nginx/.
    ports:
      - "8080:8080"
    networks:
      - api-internal
    # 去掉旧的links配置,同一网络下直接用api服务名访问

  api:
    # 你的API服务镜像/构建配置
    networks:
      - api-internal
    # 直接指定要启动的API实例数量
    deploy:
      replicas: 3

这样启动后,proxy服务可以直接通过api这个服务名访问所有3个API实例,Docker DNS会自动返回所有运行中的容器IP。

3. 验证负载均衡是否生效

启动所有服务后,多执行几次curl http://localhost:8080,然后:

  • 查看API容器的日志,应该能看到请求被分发到不同的实例上
  • 查看NGINX的access.log,里面的$upstream_addr字段会显示每次转发到的后端IP,确认轮询是否正常工作

内容的提问来源于stack exchange,提问作者Raj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:52:29