编辑
2025-11-18
Docker
00

目录

一、管理台有没有“完全不改代码”的同域名多后端降级功能?
二、实现办法
1. 场景与目标
2. 实现思路概述
3. 前置条件
4. 步骤一:在管理台创建/确认基础 Proxy Host
5. 步骤二:在容器中定义 upstream(同域名多服务组)
5.1 进入容器
5.2 切换到自定义配置目录
5.3 创建(或编辑)HTTP 顶层配置文件
6. 步骤三:在 Proxy Host 中使用 upstream 做转发
7. 步骤四:重启容器使配置生效
8. 步骤五:功能验证(降级容灾)
9. 回滚与多组配置说明
9.1 回滚到单后端模式
9.2 多个域名 / 多个服务组
10. 关键结论

一、管理台有没有“完全不改代码”的同域名多后端降级功能?

以现在用的 Nginx Proxy Manager 2.11.3 为例,Web 管理界面只提供:

  • 每个 Proxy Host 配置 一个 “Forward Hostname / IP + Port”
  • 一个 “Custom Nginx Configuration” 文本框(本质是 Nginx 片段)
  • Streams/Redirection/404 等基础能力

没有界面化的:

  • 多个 upstream 服务器组配置
  • 主/备后端、健康检查、权重等负载均衡选项
  • 同一 Proxy Host 下点击就能加“第二个后端”的 UI

所以,要在 同一个域名 上做“主服务 + 降级服务容灾”,只能用两类办法:

  1. 像我们现在这样
    • 用容器里 /data/nginx/custom/http_top.conf 定义 upstream(一次性手工)
    • 在 Proxy Host 的 Advanced 里用 proxy_pass http://my_backend_servers; 引用
  2. 或者把 Failover 做在 NPM 之外
    • 上游用云厂商负载均衡 / DNS 失败切换
    • NPM 只接一个已经做好的虚拟 IP 或域名

换句话说:目前没有“纯点点点、不写配置片段”的图形化降级方案,你现在这套就是标准的高级用法。


二、实现办法

主题:基于 Nginx Proxy Manager 的 Docker 容器做同域名多服务降级容灾
目标:同一个域名指向两个后端服务,主服务不可用时自动切换到降级服务(Failover),无需人工干预。

1. 场景与目标

  • 域名:example.com
  • 主服务(正常业务):主服务 A,例如 124.xxx.xxx.120:13210
  • 降级服务(简化版/静态服务):降级服务 B,例如 43.xxx.xxx.126:8001
  • 入口:Nginx Proxy Manager(Docker 容器)
  • 要求:
    • 日常所有流量走主服务 A
    • A 宕机、超时或连续失败时,自动切到 B
    • 对客户端保持域名不变

2. 实现思路概述

  1. 利用 NPM 自带的 Nginx 实例,在 HTTP 上下文 中定义一个上游服务器组 upstream my_backend_servers,包含主服务 & 降级服务。
  2. 在指定 Proxy Host 的自定义配置中,将默认的 proxy_pass 替换为指向这个 upstream。
  3. 通过 max_fails / fail_timeout 等参数控制主服务的失效判定,通过 backup 标记降级服务。
  4. 重启 NPM 容器,使自定义 HTTP 顶层配置生效。

3. 前置条件

  • 已使用 Docker 部署 Nginx Proxy Manager,容器名称假定为:nginx-docker-app-1
  • 已能正常登录 NPM 管理台(Web UI)
  • 已有一个要做容灾的 Proxy Host(域名已经在 NPM 中配置并可正常访问)

4. 步骤一:在管理台创建/确认基础 Proxy Host

  1. 登录 NPM 管理台。
  2. 点击顶部菜单 Hosts → Proxy Hosts
  3. 新建或编辑目标 Proxy Host:
    • Domain Namesexample.com
    • Schemehttphttps(视后端实际情况)
    • Forward Hostname / IP:填主服务 IP,例如 124.xxx.xxx.120
    • Forward Port:主服务端口,例如 13210
    • 其他(SSL、认证等)按原有配置保持不变。
  4. 点击 Save,确认此时通过域名访问可以正常到达主服务 A。

说明:这一步只是建立一个基础可用的 Proxy Host,后续我们会在其上“接管”转发逻辑。


5. 步骤二:在容器中定义 upstream(同域名多服务组)

5.1 进入容器

在宿主机执行:

bash
docker exec -it nginx-docker-app-1 /bin/bash

5.2 切换到自定义配置目录

bash
cd /data/nginx/custom/

若目录不存在可创建:

bash
mkdir -p /data/nginx/custom cd /data/nginx/custom

5.3 创建(或编辑)HTTP 顶层配置文件

你的 nginx.conf 已经包含:

nginx
include /data/nginx/custom/http_top[.]conf;

所以我们需要创建的文件名必须是 http_top.conf(中括号在配置里是转义用的)。

安装编辑器(如未安装):

bash
apt-get update && apt-get install -y vim

编辑/创建文件:

bash
vim http_top.conf

写入内容(示例 IP & 端口按你的实际环境替换):

nginx
# HTTP 顶层自定义配置:上游服务器组(主 + 降级) upstream my_backend_servers { # 主服务 A server 124.xxx.xxx.120:13210 max_fails=3 fail_timeout=10s; # 降级服务 B:仅在所有非 backup 服务器不可用时启用 server 43.xxx.xxx.126:8001 backup; }

保存退出

说明:

  • max_fails=3:在 fail_timeout 时间窗口内,连接失败 3 次即认为此后端暂时不可用。
  • fail_timeout=10s:失败后 10 秒内不再尝试该后端,之后会重新探测。
  • backup:将该后端标记为备用。只有所有非 backup 的 upstream 都失效时才会使用。

完成后退出容器:

bash
exit

注:备用方式将配置写入 my_upstream.conf**

  1. 使用 cathere-document 将内容直接重定向到文件:

    bash
    cat <<'EOF' > my_upstream.conf upstream my_backend_servers { server 124.xxx.xxx.120:13210 max_fails=3 fail_timeout=10s; server 43.xxx.xxx.126:8001 backup; } EOF

    该方法不依赖任何文本编辑器即可生成或覆盖文件,适用于临时或脚本化场景。

    here-document: 是一种将多行文本写入命令或文件的方式,使用 <<'EOF' 语法可以避免变量展开;常用于批量写入配置。

  2. 如果希望在追加而不覆盖的情况下写入内容,也可使用 tee

    bash
    cat <<'EOF' | tee my_upstream.conf upstream my_backend_servers { server 124.xxx.xxx.120:13210 max_fails=3 fail_timeout=10s; server 43.xxx.xxx.126:8001 backup; } EOF

    tee 默认会输出到标准输出,同时写入目标文件;通过重定向符 < 可以控制覆盖或追加(如 tee my_upstream.conf 会覆盖)。

    tee: 同时向标准输出和一个或多个文件写入数据的命令,常用于记录中间输出。

  3. 修改完配置后,使用 nginx -t 进行语法校验并重载:

    bash
    nginx -t && nginx -s reload

    先进行语法校验再重载能避免因配置错误导致 nginx 无法启动。

    nginx -t: 用于测试配置文件语法是否正确,同时检查包含文件与语法逻辑;若语法无误则返回 OK。


6. 步骤三:在 Proxy Host 中使用 upstream 做转发

  1. 回到 NPM 管理台,编辑刚才的 Proxy Host。
  2. 切换到 Advanced(自定义 Nginx Configuration)标签。
  3. 清空现有内容,填入:
nginx
location / { proxy_pass http://my_backend_servers; proxy_set_header Host $host; }

说明:

  • 这里不再使用 $forward_scheme://$server:$port,而是显式指定 upstream 名称 my_backend_servers
  • 如需保留源 IP 等头信息,可在此处进一步补充:
    nginx
    proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
  1. 点击 Save。此时 UI 可能短暂显示 Offline,属正常现象,下一步会处理。

7. 步骤四:重启容器使配置生效

在宿主机执行:

bash
docker restart nginx-docker-app-1

等待容器重启完成后,重新登录 NPM 管理台,目标 Proxy Host 应显示为 Online

如需验证,可在容器内执行一次配置检查:

bash
docker exec -it nginx-docker-app-1 nginx -t

确保输出包含:

text
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful

8. 步骤五:功能验证(降级容灾)

  1. 正常场景验证

    • 保持主服务 A、降级服务 B 均运行。
    • 通过浏览器或 curl 访问 https://example.com/
    • 确认返回的是主服务 A 的内容。
  2. 降级场景验证

    • 暂停或关闭主服务 A(例如停止应用、关闭端口等)。
    • 再次访问 https://example.com/
    • 确认返回内容已切换为降级服务 B。
    • 恢复主服务 A 后,新请求会自动回切到主服务 A。

9. 回滚与多组配置说明

9.1 回滚到单后端模式

若要取消同域名多服务降级容灾:

  1. 管理台中,清空 Proxy Host 的 Advanced 配置(让 NPM 恢复默认 location /)。
  2. 在容器中,将 /data/nginx/custom/http_top.conf 中对应的 upstream 删掉或注释。
  3. docker restart nginx-docker-app-1

9.2 多个域名 / 多个服务组

如有多个域名需要不同的主/备服务组合,可在 http_top.conf 中定义多个 upstream,例如:

nginx
upstream app1_backends { ... } upstream app2_backends { ... }

然后在不同 Proxy Host 的 Advanced 区分别:

nginx
location / { proxy_pass http://app1_backends; proxy_set_header Host $host; }

nginx
location / { proxy_pass http://app2_backends; proxy_set_header Host $host; }

10. 关键结论

  • NPM 管理台本身不提供无代码的“多后端 + 主备降级”按钮。
  • 利用 NPM 预留的 /data/nginx/custom/http_top.conf + Proxy Host Advanced 配置,可以在 不直接改主 nginx.conf 的前提下,实现同域名多服务降级容灾。
  • 该方案兼容现有 NPM 架构,对其他 Proxy Host 影响可控,可复制扩展到多域名场景。