207 服务入口与断电重启恢复
本文解决什么:207 断电 / 重启 / 崩过一轮之后,按「先看哪个页面 → 什么顺序拉起来 → 怎么确认真的好了」一条线走完;顺带把这台机器上的统一服务入口页(
:8090)讲清楚。不是:Dify 单点故障的排查(走专题一到十七)、GPU 推理侧调优(那是 116 的事)、业务容量规划(走专题十四)。
环境:应用主机
192.168.110.207(Ubuntu 22.04);Dify 1.16.1 / LiteLLM / Langfuse / Xinference / Higress / k3s 同机共存,所以谁都可能被别人拖慢。HTML:
docs/html_cursor/运维_207服务入口与断电重启恢复_cursor.html附件:
scripts_cursor/运维_207服务入口与断电重启恢复/(_reboot_restore_207.py·_reboot_check.py·_portal_8090_index.html)关联:平台服务汇总 · 入口与架构 · 作业5 vLLM 健康检查 · 作业7 故障自愈工作流 · 作业13 虚拟模型主备与压测
目录
1. 先说结论:一页看全
入口页(先在浏览器打开这一个):
http://192.168.110.207:8090/ ← 207 服务入口页(所有可点服务的卡片)恢复顺序(一句话版):
探活定位 → docker → litellm → Dify compose → Langfuse → Xinference
→ Higress → 监控(hw8) → k3s + GitLab demo → 等 45s → 再探活探活表(11 项,全部 2xx 才算「恢复完成」):
| # | 服务 | 探活地址 | 期望 |
|---|---|---|---|
| 1 | Dify | http://192.168.110.207/ | 200 |
| 2 | LiteLLM | http://192.168.110.207:4000/health/liveliness | 200 |
| 3 | Langfuse | http://192.168.110.207:3000/api/public/health | 200 |
| 4 | Xinference | http://192.168.110.207:9997/v1/models | 401(无 Key 也是活的) |
| 5 | Higress Gateway | http://192.168.110.207:18080/ | 200 / 404 |
| 6 | Higress Console | http://192.168.110.207:8001/ | 200 |
| 7 | GitLab(demo) | http://192.168.110.207:8929/users/sign_in | 200 |
| 8 | Argo CD(demo) | http://192.168.110.207:30080/ | 200 |
| 9 | demo-nginx | http://192.168.110.207:30088/ | 200 |
| 10 | Grafana | http://192.168.110.207:3001/ | 200 |
| 11 | Prometheus | http://192.168.110.207:9092/-/ready | 200 |
注意 Xinference 那一行:
:9997/v1/models不带 Key 返回 401 是正常的,说明进程活着、只是在鉴权;返回Connection refused才是真挂了。别把 401 当故障。
2. 服务入口页(:8090)是怎么做的
2.1 为什么要它
207 上同时跑着 Dify、Langfuse、LiteLLM、Xinference、Higress、Grafana、GitLab、Argo CD……入口散在十几个端口上。断电重启后第一件事是「哪些服务该起来、端口是多少、点哪个」,靠记忆容易漏。
于是做了一个纯静态的服务入口页:一个 HTML,把「能从浏览器打开的东西」按 应用 / 模型与网关 / 监控 / 代码与接口 四组铺成卡片,顶部一个搜索框。
2.2 怎么实现的(只要一个 systemd + 一个目录)
不用 Nginx、不用 Node,Python 自带的静态服务器就够:
# /etc/systemd/system/host-portal.service
[Unit]
Description=Host service portal
After=network-online.target
[Service]
ExecStart=/usr/bin/python3 -m http.server 8090 --bind 0.0.0.0 --directory /var/www/portal
Restart=on-failure
RestartSec=2
[Install]
WantedBy=multi-user.target# 落地
mkdir -p /var/www/portal
cp _portal_8090_index.html /var/www/portal/index.html
systemctl daemon-reload
systemctl enable --now host-portal
systemctl is-active host-portal # active
curl -s -o /dev/null -w '%{http_code}\n' http://192.168.110.207:8090/ # 200三个要点:
| 要点 | 说明 |
|---|---|
--bind 0.0.0.0 | 只写 127.0.0.1 的话别人访问不到 |
--directory /var/www/portal | 页面文件在 /var/www/portal/index.html,改页面就是覆盖这个文件 |
Restart=on-failure | 崩了自动起;但开机自启要靠 systemctl enable |
2.3 页面里放什么
卡片是 [名称, 说明, URL] 三元组,四组;URL 用 访问者当前 IP 拼,所以内网/外网换 IP 访问都不用改:
const host = location.hostname || "192.168.110.207";
const http = (port, path) => "http://" + host + (port === 80 ? "" : ":" + port) + (path || "/");const groups = [
{ title: "应用", items: [
["Dify", "对话应用与工作流", http(80)],
["Langfuse", "LLM 调用观测", http(3000)],
["DeepSeek Harness", "DeepSeek 控制台", http(3080)],
["办公 IP 云同步", "办公网 IP 同步控制台", http(8765)],
["Hindsight", "记忆服务 API 文档", http(18888, "/docs")],
]},
{ title: "模型与网关", items: [
["LiteLLM 控制台", "模型网关管理界面", http(4000, "/ui")],
["LiteLLM API", "网关接口文档", http(4000)],
["Xinference", "本地模型推理", http(9997)],
["Higress 控制台", "网关配置", http(8001)],
["Higress 网关", "HTTP 入口", http(18080)],
["Nacos", "配置与注册中心", http(8888)],
]},
{ title: "监控", items: [
["Grafana", "指标看板", http(3001)],
["Prometheus", "指标查询", http(9092)],
]},
{ title: "代码与接口", items: [
["GitLab", "代码仓库", http(8929)],
["服务器状态 API", "接口文档", http(8777, "/docs")],
["工单 API", "接口文档", http(8778, "/docs")],
["vLLM 健康检查", "接口文档", http(8779, "/docs")],
["vLLM 自愈 API", "接口文档", http(8780, "/docs")],
]},
];改页面 = 改这个数组 → 覆盖 /var/www/portal/index.html(不用重启服务,http.server 每次请求都重读文件)。
建议先备份再覆盖:
cp index.html index.html.bak_$(date +%Y%m%d)。
3. 端口与服务全清单(实测)
2026-10-13 在 207 上实扫(docker ps + ss -lntp + systemctl 三处对齐):
3.1 宿主进程 / systemd 服务
| 端口 | 服务 | 载体 | 说明 |
|---|---|---|---|
| 22 | SSH | sshd | |
| 80 | Dify 控制台 | nginx → 127.0.0.1:8089 | 反代 /etc/nginx/conf.d/dify.conf |
| 443 | nginx(其它域名) | nginx | dbblive / harbor 等 vhost |
| 3080 | DeepSeek Harness | deepseek-harness.service | 指向 116 vLLM 的对话 UI |
| 3306 | MySQL | mysqld | |
| 4000 | LiteLLM | litellm.service | 统一 OpenAI 网关 |
| 6443 | k3s API Server | k3s.service | |
| 8000 | Yearning(SQL 审核) | nginx → 192.168.122.190:8000 | vhost yearning.conf |
| 8090 | 服务入口页 | host-portal.service | /var/www/portal |
| 8765 | 办公 IP 云同步控制台 | office-sync-web.service | |
| 8777 | 服务器状态 API | python3 | /docs |
| 8778 | 工单 API | python3 | /docs |
| 8779 | vLLM 健康检查 API | python3 | /docs |
| 8780 | vLLM 自愈 API | python3 | /docs |
| 18888 | Hindsight API | hindsight-api.service | /docs |
3.2 容器(docker)
| 端口 | 容器 | 说明 |
|---|---|---|
| 3000 | langfuse-langfuse-web-1 | Langfuse Web |
| 3001 | hw8-grafana | Grafana(SLA 大盘) |
| 3030 | langfuse-langfuse-worker-1 | 仅 127.0.0.1 |
| 5003 | docker-plugin_daemon-1 | Dify 插件守护 |
| 5432 | langfuse-postgres-1 | 仅 127.0.0.1 |
| 8001 | higress-console-1 | Higress 控制台 |
| 8088 | docker-weaviate_relay-1 | socat 中继 → weaviate 8080 |
| 8089 | docker-nginx-1 | Dify 前端(80 的上游) |
| 8449 | docker-nginx-1 | Dify 前端 TLS |
| 8888 | higress-nacos-1 | Nacos 控制台(容器内 8080) |
| 8929 | gitlab-argocd-demo | GitLab(Argo CD 演示) |
| 9090 | langfuse-minio-1 | 不是 Prometheus |
| 9091 | langfuse-minio-1 | MinIO Console,仅 127.0.0.1 |
| 9092 | hw8-prometheus | Prometheus |
| 9848 | higress-nacos-1 | Nacos 主端口 |
| 9997 | xinference | bge-m3 / bge-reranker |
| 15020 | higress-gateway-1 | 健康/mesh |
| 18080 / 18443 | higress-gateway-1 | 总入口 HTTP / HTTPS |
| 18848 | higress-nacos-1 | 容器内 8848 |
| 2224 | gitlab-argocd-demo | GitLab SSH |
3.3 k3s NodePort(kube-proxy 转发,ss 里看不到)
| 端口 | Service | 说明 |
|---|---|---|
| 30080 | argocd/argocd-server | Argo CD Web UI |
| 30088 | argocd-demo/demo-nginx | GitOps 演示应用 |
易踩的坑:
:9090是 MinIO(Langfuse 的对象存储),Prometheus 在:9092;:8888是 Higress 自带的 Nacos 控制台,不是业务服务。
4. 断电重启恢复 Runbook
4.1 顺序为什么是这样
207 是一台机器跑一整套栈,依赖是链式的:
docker(一切容器的前提)
└─ litellm(systemd,依赖网络)
└─ Dify compose(api / worker / web / nginx / plugin_daemon / db / redis / weaviate / sandbox)
└─ 依赖 LiteLLM(:4000) 与 Xinference(:9997)
└─ Langfuse compose(web / worker / postgres / clickhouse / redis / minio)
└─ Xinference(独立容器)
└─ Higress compose(gateway / console / pilot / controller / nacos / prometheus / grafana / loki)
└─ 监控 hw8(grafana / prometheus)
└─ k3s(NodePort → Argo CD / demo-nginx)所以先底盘(docker / k3s)→ 再中间件(litellm / Dify / Langfuse / Xinference)→ 再入口(Higress)→ 最后监控,最后等容器把依赖关系走完。
4.2 一键跑(推荐)
# Windows 开发机(本机)
python _reboot_restore_207.py_reboot_restore_207.py 做的事情,逐条对应后面的手工步骤:
| 步 | 动作 | 关键命令 |
|---|---|---|
| 0 | 先探活(不看状态就动手是盲修) | 11 项 HTTP 探活表 |
| 1 | Docker | systemctl enable docker; systemctl start docker |
| 2 | LiteLLM | systemctl enable litellm; systemctl restart litellm |
| 3 | Dify | cd /dify/dify-main/docker && docker compose up -d |
| 4 | Langfuse | cd /Langfuse/langfuse && docker compose up -d |
| 5 | Xinference | docker start xinference |
| 6 | Higress | cd /opt/higress/compose && docker compose up -d |
| 7 | 监控 hw8 | cd /opt/workbuddy/patches_cursor/作业8_SLA监控大盘 && docker compose -f docker-compose.monitoring.yml up -d |
| 8 | k3s + GitLab demo | systemctl enable k3s; systemctl start k3s;docker start gitlab-argocd-demo |
| 9 | 等 45s 让依赖走完 | sleep 45 |
| 10 | 再探活 | 同一张 11 项表 |
脚本用 SSH 密钥(
C:\Users\DCKJ\.ssh\id_ed25519)连 207,不再走密码;get_pty=True是为了让docker compose的彩色输出与交互式提示正常返回。
4.3 只看不修(先体检)
python _reboot_check.py输出 5 段:uptime / free -h、systemctl is-active+is-enabled docker k3s litellm、docker ps -a、ss -tlnp 关键端口、k3s 节点与 Pod。给别人看现场、或者决定要不要重启之前,先跑这个。
4.4 手工版(脚本跑不动时照这个抄)
# 1) 底盘
systemctl start docker; systemctl is-active docker
# 2) LiteLLM
systemctl restart litellm; curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:4000/health/liveliness
# 3) Dify
cd /dify/dify-main/docker && docker compose up -d && docker compose ps
# 4) Langfuse
cd /Langfuse/langfuse && docker compose up -d
# 5) Xinference
docker start xinference
# 6) Higress
cd /opt/higress/compose && docker compose up -d
# 7) 监控
cd /opt/workbuddy/patches_cursor/作业8_SLA监控大盘 && docker compose -f docker-compose.monitoring.yml up -d
# 8) k3s
systemctl start k3s
KUBECONFIG=/etc/rancher/k3s/k3s.yaml k3s kubectl get pods -A | head -30# 9) 统一收口:11 项探活
for u in \
http://192.168.110.207/ \
http://192.168.110.207:4000/health/liveliness \
http://192.168.110.207:3000/api/public/health \
http://192.168.110.207:9997/v1/models \
http://192.168.110.207:18080/ \
http://192.168.110.207:8001/ \
http://192.168.110.207:8929/users/sign_in \
http://192.168.110.207:30080/ \
http://192.168.110.207:30088/ \
http://192.168.110.207:3001/ \
http://192.168.110.207:9092/-/ready ; do
printf '%-50s ' "$u"; curl -s -o /dev/null -w '%{http_code}\n' --max-time 8 "$u"
done4.5 三条经验
| 现象 | 原因 | 处置 |
|---|---|---|
docker compose up -d 卡住不动 | 镜像要拉、或容器在等依赖 | 别 Ctrl-C;命令给了 600s 超时,耐心等 |
| Dify 页面 502,但容器都是 Up | 上游 :8089 没起,nginx 80 反代断 | docker compose ps 看 docker-nginx-1,docker compose up -d nginx |
k3s Pod 全 Pending | 刚开机 containerd 还没稳 | 等 1–2 分钟再 kubectl get pods -A |
5. 大模型(vLLM)不可用时的处置策略
这一节针对「经常大模型不能用」这个高频现象。207 本身不产生模型,它只是把 116 的 vLLM 接进来;所以「不能用」要分三层看,处置手段完全不同。
5.1 三层定性(先分清是哪一层)
Dify 应用
└─(1) LiteLLM :4000 ──(2)──> vLLM 116.62.10.183:8000| 层 | 探活 | 如果这层挂了 |
|---|---|---|
| ① 网关层 | curl -s -o /dev/null -w '%{http_code}\n' http://192.168.110.207:4000/health/liveliness | 重启 litellm.service |
| ② 上游推理层 | curl -s http://116.62.10.183:8000/v1/models | vLLM 侧的事,见 5.3 |
| ③ 应用层 | curl -s -H 'Authorization: Bearer sk-litellm-bocheng-207' http://192.168.110.207:4000/v1/models | 有返回说明 ①②都通,问题在 Dify 配置 |
一条命令分完层:
echo "网关: $(curl -s -o /dev/null -w '%{http_code}' --max-time 5 http://192.168.110.207:4000/health/liveliness)"
echo "上游: $(curl -s -o /dev/null -w '%{http_code}' --max-time 5 http://116.62.10.183:8000/v1/models)"
echo "模型: $(curl -s --max-time 5 -H 'Authorization: Bearer sk-litellm-bocheng-207' \
http://192.168.110.207:4000/v1/models | head -c 200)"5.2 平台已经配好的「抗抖动」手段
根因先说:116 的 H20 与业务进程共享(mxh_env / mxh_live),业务一上来显存/算力就被抢,vLLM 侧表现为偶发超时、排队、甚至 OOM 重启。这不是 207 能修的,只能在 207 侧把抖动吃掉。
| 手段 | 现状配置 | 位置 |
|---|---|---|
| 重试 | num_retries: 2 | /opt/litellm/config.yaml → litellm_settings |
| 超时 | request_timeout: 300 | 同上 |
| 同名多部署分流 | demo-lb / demo-lb-a / demo-lb-b | model_list,验证分流机制 |
| 分流算法 | routing_strategy: simple-shuffle | router_settings |
| 健康检查 | 作业5 · :8779 | vLLM 探活 Agent |
| 自愈 | 作业7 · :8780 | OOM 检测 + 重启 vLLM + 钉钉通知 |
| 主备切换 | 作业13 / 作业17 | 虚拟模型主备、模型路由发布 Runbook |
一句话策略:上游不稳定 → 网关层重试 + 超时兜底 + 备模可切;不要在 Dify 应用里塞重试(同一请求会叠倍放大到上游)。
5.3 分级处置(照表执行)
| 级别 | 现象 | 动作 | 期望 |
|---|---|---|---|
| L1 | 偶发一次超时 / 429 | 什么都不做(num_retries: 2 会吃掉) | 自动恢复 |
| L2 | 连续失败,/v1/models 仍 200 | 看 LiteLLM 日志与 Langfuse Trace 定位是哪个模型;必要时把 Dify 默认模型临时切到备模 | 会话恢复 |
| L3 | 116 /v1/models 不通 | 上 116 看 nvidia-smi 与 vLLM 容器;→ 作业5/7 的探活与自愈 | vLLM 起回来 |
| L4 | 116 起不来 / 长期不可用 | 走 作业13 虚拟模型主备:把 primary 指到备上游,客户端不用改;改完记审计 | 业务先恢复 |
| L5 | 207 自己也重启了 | 走本文第 4 节:先恢复 207 的栈,再回到 L2 判模型 | 全栈恢复 |
| L6 | 链路全绿(①②③ 都通),但 Dify 里模型标「不可用」/ 列表空 | 不是链路问题——是 Dify 侧 openai 插件的 schema 补丁被升级冲掉了,见 5.5 | 列表恢复 active |
看日志的两个位置(顺序别搞反):
# LiteLLM(systemd,最容易看出上游超时/429)
journalctl -u litellm -n 200 --no-pager | tail -60
# Dify api / worker
cd /dify/dify-main/docker && docker compose logs --tail=200 api worker5.4 值班时的最小动作清单
① 打开 http://192.168.110.207:8090/ → 确认入口页本身还在(207 活着)
② 跑三层定性那一组 curl → 判是 ①网关 / ②上游 / ③应用
③ ①层挂 → restart litellm ③层挂 → 查 Dify 模型供应商配置
②层挂 → 上 116(或作业5/7/13)
④ 恢复后看 Langfuse Trace 确认新请求正常,并记一条值班日志5.5 另一类「不能用」:链路全通,但 Dify 里模型标「不可用」
三层定性全绿(4000 活着、116 有 /v1/models、Dify 也能取到模型), Agent 配置页却标橙「不可用」/ 右侧红框 / model-types/llm 的 data 变空 —— 这不是模型链路的问题,而是 Dify 的 openai 插件被自动升级后,自定义基座的 schema 补丁落到了旧目录。
背景:Dify 有个 Celery 定时任务(process_tenant_plugin_autoupgrade_check_task)每天按 category 自动升级插件。 langgenius/openai 属于 model 类,一旦被升级,卷里就多出一个没打补丁的新版本目录,模型立刻「不可用」。
已经做的根治(2026-09-24 05:41 起):把 model 类的自动升级关掉,并把 langgenius/openai 加入排除名单, 所以不会再出现「修好过、过几天又坏」。
一条命令复核策略还在不在:
docker exec docker-db_postgres-1 psql -U postgres -d dify -c \
"select category, strategy_setting, upgrade_mode, exclude_plugins::text,
to_char(updated_at,'YYYY-MM-DD HH24:MI') as updated
from tenant_plugin_auto_upgrade_strategies where category='model';"期望:disabled / exclude / ["langgenius/openai"]。
| 情况 | 处理 |
|---|---|
策略是 disabled + 排除 openai,但模型仍「不可用」 | 多半是手动装新版后没补丁 → 跑 专题一_04 遍历全版本重打 |
策略不是 disabled | 说明被改回去了 → 按专题十七 §5 重新关闭 |
| 关掉后想升 openai 插件 | 手动升 → 立刻跑 专题一_04 → 刷新模型列表 |
排查脚本(只读):
python scripts_cursor/Dify_专题十七_OpenAI插件升级后schema补丁丢失/专题十七_01_查看插件自动升级策略.py完整原理、三种改法与验收见专题十七 · OpenAI 插件升级后 schema 补丁丢失。
6. 常见问题
| 问题 | 原因 | 处置 |
|---|---|---|
入口页 :8090 打不开 | host-portal.service 没起 / 没 enable | systemctl enable --now host-portal |
| 入口页打开了但卡片全点不动 | 卡片 URL 按 location.hostname 拼,本机访问会拼成 127.0.0.1 | 用 192.168.110.207:8090 打开 |
改了 /var/www/portal/index.html 页面没变 | 浏览器缓存 | 强刷(Ctrl+F5) |
systemctl is-active 是 active,但网页打不开 | 端口被占 / 只绑了 127.0.0.1 | `ss -lntp \ |
| 断电后 Dify 起来了但模型不可用 | 依赖链:Dify → LiteLLM → 116,后两者没起来 | 按第 4 节顺序补起,再走第 5 节判定 |
docker compose 报 no configuration file | 没 cd 到 compose 目录 | Dify 在 /dify/dify-main/docker,Higress 在 /opt/higress/compose |
7. 验收与回滚
验收(11 项探活全 2xx + 一个真实对话):
# 全部探活
python _reboot_restore_207.py # 末尾会再打一遍探活表
# 真实对话(走 LiteLLM)
curl -s http://192.168.110.207:4000/v1/chat/completions \
-H 'Authorization: Bearer sk-litellm-bocheng-207' \
-H 'Content-Type: application/json' \
-d '{"model":"qwen3.6-27b","messages":[{"role":"user","content":"ping"}],"max_tokens":16}'回滚 / 备份:
| 对象 | 备份方式 |
|---|---|
| 入口页 | cp /var/www/portal/index.html /var/www/portal/index.html.bak_$(date +%Y%m%d) |
| LiteLLM 配置 | cp /opt/litellm/config.yaml /opt/litellm/config.yaml.bak_$(date +%Y%m%d) |
| Dify compose | 改前 cp docker-compose.yaml docker-compose.yaml.bak_$(date +%Y%m%d) |
| 服务单元 | 改前 systemctl cat <unit> > /root/<unit>.bak |
恢复动作只重启服务、不删数据:所有 compose 都用
up -d,从不down -v。数据卷(/dify/dify-main/docker/volumes、Langfuse 的 postgres/clickhouse/minio)不在恢复脚本的动手范围内。
*本文的「端口与服务全清单」为 2026-10-13 在 207 实扫结果;新增或调整服务后请同步更新第 3 节与入口页卡片数组。*