CyTube 配置参数详解
CyTube 3.86.1 配置体系逐段详解:config.yaml 全参数(mysql/listen/http/https/io/站务限制/频道行为/播放队列/ffmpeg/service-socket 等)与 conf/ 四个扩展文件(camo/captcha/email/prometheus),关键参数附改值+重启+生效回显实测:站点标题改值、update-interval 采样 2.00s、聊天长度截断行为、保留名正则五组对比、channel_data 落库与 prometheus /metrics。
CyTube 配置参数详解
目标:把 CyTube 3.86.1 的配置体系彻底讲透。以官方模板
config.template.yaml(217 行,注释即文档)为底本逐段拆解每个配置项的含义、默认值与取值注意点,再补上conf/目录下的四个扩展配置(camo/captcha/email/prometheus)。关键参数全部附"改值 → 重启 → 生效回显"的实测闭环,回显逐行照抄自真实部署现场。部署过程见《CyTube Docker Compose 部署实战》,日常运维见《CyTube 常用命令与运维实战(核心篇)》。
一、配置体系总览
CyTube 的配置由两层组成:主配置 config.yaml(YAML,位于应用运行目录)与 conf/ 目录下的扩展配置(TOML,按功能拆文件)。主配置负责站点骨架(数据库、监听端口、站务限制),扩展配置负责可选能力(验证码、邮件、指标暴露、图片代理)——不放文件就是关闭,应用启动时逐个探测并在日志里报告探测结果。
实测启动日志的配置加载段(docker logs 逐行照抄):
[INFO] config: Loaded configuration from config.yaml
[INFO] config: No camo configuration found, chat images will not be proxied.
[INFO] config: Loaded prometheus configuration from conf/prometheus.toml. Prometheus listener is ENABLED
[INFO] config: No email configuration found, defaulting to disabled
[INFO] config: No captcha configuration found, defaulting to disabled
四行 config: 日志就是配置体系的自述:主配置已加载;conf/camo.toml 不存在 → 图片代理关闭;conf/prometheus.toml 存在且启用 → 指标监听开启;邮件、验证码未配置 → 默认关闭。排障第一步永远是看这段日志。
此外,CyTube 启动时会对配置做一致性自检,用管理命令行触发一次完整的 WARN 清单(回显逐行照抄):
[WARN] config: Detected 127.0.0.1 or localhost in root-domain 'localhost'. This server will not work from other computers! Set root-domain to the domain the website will be accessed from (e.g. example.com)
[WARN] config: socket.io is bound to localhost, this server will be inaccessible from other computers!
[WARN] config: No YouTube v3 API key set. YouTube links will not work. See youtube-v3-key in config.template.yaml and https://developers.google.com/youtube/registering_an_application for information on registering an API key.
[WARN] config: No Twitch Client ID set. Twitch VOD links will not work. See twitch-client-id in config.template.yaml and https://github.com/justintv/Twitch-API/blob/master/authentication.md#developer-setupfor more information on registering a client ID
这四条 WARN 覆盖了新手最常踩的四个坑:域名写 localhost(外部无法访问)、实时通道绑本地、缺 YouTube API Key(站内搜不到 YouTube 视频)、缺 Twitch Client ID(VOD 查询失效)。真实上线前逐条消除即可。
💡 技术拓展:CyTube 的配置校验是"宽松加载"策略——未知键、缺失键都不报错,缺失项回落到源码
src/config.js里的内置默认值(与config.template.yaml的数值一致)。因此配置文件里没写的参数也在生效,逐段核对模板文件是确认默认行为的唯一可靠途径。
二、数据库连接(mysql 段)
模板默认:
mysql:
server: 'localhost'
port: 3306
database: 'cytube3'
user: 'cytube3'
password: ''
pool-size: 10
| 参数 | 说明 |
|---|---|
server | 数据库地址,域名、IP 或 UNIX 套接字路径(套接字写法 unix:/path/to/sock.sock) |
port | 端口,默认 3306 |
database / user / password | 库名与账号;官方要求 MySQL/MariaDB ≥ 5.5.3 且字符集 utf8mb4 |
pool-size | 连接池大小,默认 10;频道多、Socket 并发高时可加大 |
实测要点:server 写编排栈内的服务名即可(同网络内服务名即主机名),本实验为 cytube-3.86.1-mariadb。库与账号由 MariaDB 初始化变量自动创建,首启迁移自动建 14 张表(实测 show tables; 回显见《CyTube Docker Compose 部署实战》4.2 节)。
三、监听端口(listen 数组)
模板默认与注释要点:
listen:
- ip: ''
port: 8080
http: true
- ip: ''
port: 1337
io: true
规则(源自模板注释原文):
- 每个条目必须给出
ip和port,ip留空字符串表示绑定全部网卡; - 每个条目用
http/https/io三个布尔值声明该端口承载的服务;http+io(或https+io)可以合并到一个端口;但http与https同时声明时只有 https 生效; - 可用
url键为该端口指定对外的完整地址(反代场景用)。
本实验的监听配置(实测生效):8080 承载 http(页面/接口),1337 承载 io(实时通道),分别对外映射为 8129/8130。实时通道探活实测:
curl -s "http://localhost:8130/socket.io/?EIO=4&transport=polling" | head -c 60
实测回显:
0{"sid":"lvJnPptR3Zw1-Vxb","upgrades":["websocket"],...
💡 技术拓展:官方 Wiki 附录的生产建议是"反代只转发 HTTP,WebSocket 走 8443 的 HTTPS 端口直连"——即
listen中再加一个https: true, io: true的 8443 条目(同时打开https.enabled并配好证书)。这是因为许多反代对长连接 WebSocket 的超时/缓冲处理不佳,直连 TLS 端口更稳。
四、HTTP 服务(http 段)
模板全量:
http:
default-port: 8080
root-domain: 'localhost'
alt-domains:
- '127.0.0.1'
minify: false
max-age: '7d'
gzip: true
gzip-threshold: 1024
cookie-secret: 'change-me'
index:
max-entries: 50
trust-proxies: ['loopback']
| 参数 | 默认 | 说明 |
|---|---|---|
default-port | 8080 | 生成链接时使用的默认 HTTP 端口 |
root-domain | localhost | 登录 Cookie 的绑定根域;多子域站点(a.example.com/b.example.com)填 example.com |
alt-domains | ['127.0.0.1'] | 额外允许签发登录 Cookie 的域名/主机名列表 |
minify | false | 是否压缩 CSS/JS(express-minify) |
max-age | '7d' | 静态资源缓存时长(ms 模块格式,0 禁用) |
gzip / gzip-threshold | true / 1024 | gzip 开关与触发阈值(字节),启动日志 webserver: Enabled gzip compression 即此参数回显 |
cookie-secret | change-me | Cookie 签名密钥,必须改成随机长串;泄露等于可伪造登录态 |
index.max-entries | 50 | 首页公开频道列表最多展示条数 |
trust-proxies | ['loopback'] | 信任的代理地址段(proxy-addr 语法),用于把 X-Forwarded-For 映射为真实客户端 IP——IP 限流、封禁、别名记录都依赖真实 IP,反代场景必配 |
实测:改 html-template.title 验证配置生效链路(html-template 段与 http 段同属页面呈现,此处一并实测)。把标题从 CyTube 改为 CyTube 实验室:
sed -i "s/title: 'CyTube'/title: 'CyTube 实验室'/" conf/config.yaml
docker restart cytube-3.86.1-app
sleep 6 && curl -s http://localhost:8129/ | grep -o '<title>[^<]*</title>'
实测回显:
cytube-3.86.1-app
<title>CyTube 实验室</title>
页面 <title> 已变为新值——主配置改值 → 服务重启 → 页面回显的生效链路验证通过。
五、HTTPS 服务(https 段)
模板默认(全部关闭态):
https:
enabled: false
default-port: 8443
domain: 'https://localhost'
keyfile: 'localhost.key'
passphrase: ''
certfile: 'localhost.cert'
cafile: ''
ciphers: 'HIGH:!DSS:!aNULL@STRENGTH'
| 参数 | 说明 |
|---|---|
enabled | 总开关;开启后还需在 listen 数组加 https: true 的条目才真正监听 |
default-port / domain | 生成 HTTPS 链接的默认端口与域名前缀 |
keyfile / certfile / cafile / passphrase | 证书私钥、证书、CA 链与私钥口令(相对应用运行目录) |
ciphers | OpenSSL 加密套件表达式,默认即禁用 DSS/无认证套件 |
本实验未启用 HTTPS(隔离内网直连 HTTP)。上生产必须启用:直链视频与登录 Cookie 都受浏览器安全策略约束,全站 HTTPS 是硬要求。
六、页面模板与实时通道(html-template / io 段)
html-template:
title: 'Sync'
description: 'Free, open source synchtube'
io:
domain: 'http://localhost'
default-port: 1337
ip-connection-limit: 10
cors:
allowed-origins: []
html-template.title:页面左上角站点名与<title>(实测改值见第四节);html-template.description:<meta>描述;io.domain:Socket.IO 对外的根地址。模板注释原文警告:此域的根必须与 HTTP 域的根一致(或 HTTPS 域),否则登录不生效——Cookie 按http.root-domain签发,实时通道按io.domain连接,两域根不一致时跨域不带 Cookie;io.default-port:生成 Socket.IO 连接地址的默认端口;io.ip-connection-limit: 10:单 IP 并发实时连接上限(防一个 IP 开几十个标签页刷连接);io.cors.allowed-origins:额外放行的跨域来源列表(io.domain/https.domain隐式包含)。
💡 技术拓展:
cookie-secret、root-domain、io.domain三者构成"登录铁三角"。实测排障案例:用127.0.0.1访问而root-domain为localhost时,服务端根本不下发 Cookie,注册/登录一律 403 Invalid Session(完整现象与处置见《CyTube Docker Compose 部署实战》8.1 节)。
七、第三方平台密钥
youtube-v3-key: ''
twitch-client-id: null
youtube-v3-key:YouTube Data API v3 密钥。不配则 YouTube 链接无法解析(启动 WARN 明说)。模板注释给出完整的申请步骤与自测命令:
export YOUTUBE_API_KEY="your key here"
curl "https://www.googleapis.com/youtube/v3/search?key=$YOUTUBE_API_KEY&part=id&maxResults=1&q=test+video&type=video"
twitch-client-id:Twitch 数据 API 的 Client ID,用于 VOD(回放)查询;不配则 Twitch 直播链接可用但 VOD 链接解析失败。
两个密钥都是"站点级"的:配一次全站所有频道受益。
八、注册与站务限制
模板默认:
max-channels-per-user: 5
max-accounts-per-ip: 5
guest-login-delay: 60
max-chat-message-length: 320
| 参数 | 默认 | 说明 |
|---|---|---|
max-channels-per-user | 5 | 每个账号可注册的频道数上限 |
max-accounts-per-ip | 5 | 每 IP 可注册账号数上限(防批量小号) |
guest-login-delay | 60 | 同 IP 两次游客登录的最小间隔(秒) |
max-chat-message-length | 320 | 单条聊天消息最大字符数,源码硬顶 1000 |
实测一:游客登录限流(guest-login-delay: 60)。同 IP 第二次游客登录时服务端直接拒绝,实测回显:
[15:42:37] [B(viewer)] <== login: {"success":false,"error":"Guest logins are restricted to one per IP address per 60 seconds."}
实测二:改 max-chat-message-length: 20 验证行为。配置改值重启后,经 Socket.IO 发送 24 个汉字:
[16:03:02] 发送 24 字消息(上限 20)
[16:03:02] [A(admin)] ==> chatMsg {"msg":"一二三四五六七八九十甲乙丙丁戊己庚辛壬癸子丑寅卯"}
[16:03:02] [A(admin)] <== chatMsg: {"username":"admin","msg":"一二三四五六七八九十甲乙丙丁戊己庚辛壬癸","meta":{},"time":1793203382732}
24 字消息被服务端截断为 20 字后照常广播(对照:发送 10 字消息原样通过)。这是一个容易被误解的行为——超长消息不是整条拒绝而是截断放行。
九、频道行为参数
9.1 频道路径与黑名单
channel-path: 'r'
channel-blacklist: []
channel-path:频道 URL 路径段,http://localhost/r/频道名中的r;允许字符为字母、数字、下划线、连字符;channel-blacklist:频道名黑名单数组,命中者加入即被踢(配合运维篇的封禁命令使用)。
9.2 频道快照周期(channel-save-interval)
channel-save-interval: 5
注释原文:频道状态落盘的周期(分钟),默认 5。实测改为 1 后的完整行为链(改值 → 重启 → 加频道并修改 MOTD → 观察落库):
[INFO] bgtask: Saving channels with delay 60000
[INFO] bgtask: Saved /r/movie-night
随后查库确认频道状态真的落了库(7 个模块各一行):
*************************** 5. row ***************************
channel_id: 1
key: motd
value_head: "运维篇实测:频道状态保存验证 MOTD"
*************************** 6. row ***************************
channel_id: 1
key: playlist
value_head: {"pl":[{"media":{"id":"https://10.89.60.1:8133/cytube-test.mp4","title":"CytubeLab 同步测试片","seconds":
三个实测结论:
- 3.x 的频道状态存在数据库
channel_data表(按模块分行:motd、playlist、chatbuffer、css、js等),模板注释里的"落盘"指的是写库,chandump/目录是 2.x 文件存储的遗留路径(源码明确file类型已抛异常弃用); - 周期保存只处理有在线观众的频道(源码
bgtask.js中chan.users.length > 0条件),空频道不写; - 保存走脏标记:只有发生变更的模块才写库(源码
dbstore.js中rowCount === 0直接返回),所以只进频道不改动时channel_data不会新增内容。
9.3 保留名规则(reserved-names)
模板默认:
reserved-names:
usernames:
- '^(.*?[-_])?admin(istrator)?([-_].*)?$'
- '^(.*?[-_])?owner([-_].*)?$'
channels:
- '^(.*?[-_])?admin(istrator)?([-_].*)?$'
- '^(.*?[-_])?owner([-_].*)?$'
pagetitles: []
数组里的每一项都是正则,多规则按"或"合并、不区分大小写。默认规则保留 admin/owner 前后缀变形(d-admin、admin_x 命中;dadmin 不命中——模板注释原话)。命中后的注册报错(实测回显):
That username is reserved.
实测对比矩阵(改值重启后逐个注册验证,回显取页面 alert 文案):
| 测试用户名 | 配置状态 | 结果 |
|---|---|---|
co-admin | 规则被改为 ['(?!)', '(?!)'](永不匹配的占位正则) | Registration Successful |
x-admin | 恢复默认两条正则 | That username is reserved. |
the-owner | 恢复默认两条正则 | That username is reserved. |
dadmin | 恢复默认两条正则 | Registration Successful |
co-admin2(尾缀数字) | 恢复默认两条正则 | Registration Successful |
两个实用结论:(?!) 是"全部放行"的合法写法(本实验室本地环境即用它跳过保留名限制);默认正则只匹配 admin/owner 与分隔符紧邻的变形,co-admin2 这类尾缀数字不在保护范围内,需要更严保护就自己加正则。
十、别名清理与播放队列
10.1 别名清理(aliases)
aliases:
purge-interval: 3600000
max-age: 2592000000
CyTube 会记录每个账号用过的历史用户名(别名,aliases 表),便于识别"改名的小号"。purge-interval 是清扫周期(毫秒,默认 1 小时),max-age 是别名最长保留期(毫秒,默认 30 天)。两个值都只影响清理节奏,不影响功能。
10.2 播放队列(playlist)
playlist:
max-items: 4000
update-interval: 5
max-items:播放队列最大条目数,默认 4000;update-interval:播放进度广播周期(秒),即《CyTube Docker Compose 部署实战》第七节里两端逐位一致的mediaUpdate的发送频率。
实测:把 update-interval 改为 2 后采样 20 秒(Socket.IO 客户端记录 mediaUpdate 到达时刻,相邻间隔):
[16:03:02] 采样结果:共 10 帧,相邻间隔(秒)=2.00, 2.00, 4.00, 1.00, 2.00, 2.00, 2.00, 2.00, 2.00
采样主频 2.00 秒与配置完全吻合(个别 4.00/1.00 是 30 秒短片循环重播时边界重叠所致)。改小可让进度校准更"跟手",代价是实时通道广播量增大;默认 5 秒对绝大多数场景足够。
十一、性能与媒体处理
11.1 垃圾回收与降权(aggressive-gc / setuid)
aggressive-gc: false
setuid:
enabled: false
group: 'users'
user: 'user'
timeout: 15
aggressive-gc:开启后周期限流器清理时立即触发一次 GC,要求以node --expose-gc index.js启动,否则无效(模板注释原文)。默认关闭即可;setuid:以 root 启动后延迟降权到普通用户(timeout为降权前等待毫秒数)。本实验室在构建期直接用专用普通用户运行,此段保持关闭。
11.2 直链媒体支持(ffmpeg)
ffmpeg:
enabled: false
ffprobe-exec: 'ffprobe'
开启后支持 HTTPS 直链视频(服务端用 ffprobe 探测时长/编码再全房间同步)。本实验实测开启(enabled: true),30 秒 MP4 直链入队后的元数据回显:
<== playlist: [{"media":{"id":"https://10.89.60.1:8133/cytube-test.mp4","title":"CytubeLab 同步测试片","seconds":30,"duration":"00:30","type":"fi","meta":{"codec":"mov/h264","bitrate":839.586}},...
seconds: 30 / meta.codec: mov/h264 就是 ffprobe 的探测结果。Debian/Ubuntu 若用 libav 发行版,ffprobe-exec 需改为 avprobe(模板注释原文)。
11.3 链接与杂项(link-domain-blacklist / vimeo-workaround / service-socket / poll)
link-domain-blacklist: []
vimeo-workaround: false
service-socket:
enabled: false
socket: 'service.sock'
poll:
max-options: 50
link-domain-blacklist:聊天/队列里禁止出现的域名黑名单;vimeo-workaround:Vimeo 对作者域名屏蔽的兼容开关,一般保持 false;service-socket:开启后在应用运行目录创建 UNIX 套接字service.sock,外部服务可连上去发管理命令(/gc、/globalban、/unloadchan等,完整命令清单与实战见《CyTube 常用命令与运维实战(核心篇)》)。模板注释点明用途:stdin 不可用的托管场景(如 PM2)下的管理通道。本实验室实测开启(启动日志main: Opening service socket),且bin/admin.js依赖它;poll.max-options:频道投票最大选项数,默认 50。
十二、扩展配置 conf/example 逐个详解
conf/example/ 目录下有四个扩展配置模板,复制到 conf/(去掉 .example 路径形态)即启用。四个文件实测均已在本地环境验证加载行为。
12.1 camo.toml(聊天图片代理)
[camo]
enabled = true
server = 'https://my-camo-server'
key = 'ABCDEFGH'
whitelisted-domains = [
'i.imgur.com',
'i.4cdn.org'
]
encoding = 'url'
把聊天里的图片 URL 重写到 camo 代理服务器(防止聊天图片泄露观众 IP / 混入恶意内容)。key 必须与代理侧的 CAMO_KEY 环境变量一致;whitelisted-domains 放行可信域名不走代理;encoding 选 url 或 hex 编码目标地址。未配置时启动日志提示 No camo configuration found, chat images will not be proxied.(图片直出)。
12.2 captcha.toml(hCaptcha 验证码)
[hcaptcha]
site-key = "10000000-ffff-ffff-ffff-000000000001"
secret = "0x0000000000000000000000000000000000000000"
[register]
enabled = true
注册页启用 hCaptcha。模板默认值是 hCaptcha 官方本地测试假密钥(恒通过),上生产必须换真密钥。[register] enabled = true 表示注册需要验证码。本实验室未配置此文件,注册接口实测可直连提交(回显见部署篇 5.1 节)。
12.3 email.toml(密码重置与账号删除邮件)
[smtp]
host = 'smtp.gmail.com'
port = 465
secure = true
user = 'some-user@example.com'
password = 'secretpassword'
[password-reset]
enabled = true
html-template = """...$user$...$url$..."""
text-template = """..."""
from = "Example Website <website@example.com>"
subject = "Password reset request"
[delete-account]
enabled = true
html-template = """..."""
text-template = """..."""
配 SMTP 后解锁两个能力:密码自助重置([password-reset],邮件模板中 $user$/$url$ 会被替换为用户名与 24 小时有效的重置链接)与账号删除([delete-account],提交后 7 天自动删除)。HTML 与纯文本双模板都要配,邮件客户端按能力二选一渲染。未配置时启动日志 No email configuration found, defaulting to disabled,忘记密码只能找管理员改库。
12.4 prometheus.toml(指标暴露)
[prometheus]
enabled = true
host = '127.0.0.1'
port = 19820
path = '/metrics'
独立于主 HTTP 服务的指标监听(默认 127.0.0.1:19820,端口刻意选了避开常见 exporter 的 19820)。模板注释说明:除 path 外的任何路径一律 400。本实验室把 host 改为 0.0.0.0 以便从宿主抓取,实测回显:
curl -s http://localhost:19820/metrics | head -6
# HELP cytube_media_cache_result_age_seconds Age (in seconds) of cached record
# TYPE cytube_media_cache_result_age_seconds summary
# HELP cytube_db_query_duration_seconds DB query latency (including time spent acquiring connections)
# TYPE cytube_db_query_duration_seconds summary
cytube_db_query_duration_seconds{quantile="0.01"} 0
可用指标包括数据库查询延迟分位数、频道状态加载/保存行数字节计数、活跃频道数等,接入 Prometheus 后可做"观影室负载"面板。
十三、参数速查表
最后浓缩一张全参数速查表(默认值全部取自 3.86.1 模板,打 ✅ 的为本实验室实测验证过生效链路的参数):
| 配置段 | 参数 | 默认值 | 一句话说明 |
|---|---|---|---|
| mysql | server/port/database/user/password/pool-size | localhost/3306/cytube3/cytube3/空/10 | 数据库连接与连接池 |
| listen | (数组)ip/port/http/https/io/url | 8080 http + 1337 io | 监听端口与服务标志 |
| http | default-port | 8080 | 生成链接的默认端口 |
| http | root-domain / alt-domains | localhost / ['127.0.0.1'] | Cookie 绑定域 ✅(排障验证) |
| http | cookie-secret | change-me | Cookie 签名密钥 |
| http | minify / max-age / gzip / gzip-threshold | false / 7d / true / 1024 | 静态资源压缩缓存 ✅(gzip 日志回显) |
| http | index.max-entries | 50 | 首页公开频道列表上限 |
| http | trust-proxies | ['loopback'] | 反代真实 IP 透传 |
| https | enabled 等 | false | TLS 全套(生产必开) |
| html-template | title / description | Sync / Free, open source synchtube | 站点名与描述 ✅ |
| io | domain / default-port | http://localhost / 1337 | 实时通道对外地址 |
| io | ip-connection-limit | 10 | 单 IP 并发连接上限 |
| io | cors.allowed-origins | [] | 额外跨域来源 |
| — | youtube-v3-key | 空 | YouTube Data API 密钥 |
| — | twitch-client-id | null | Twitch VOD 查询密钥 |
| — | max-channels-per-user | 5 | 每账号频道注册上限 |
| — | max-accounts-per-ip | 5 | 每 IP 注册账号上限 |
| — | guest-login-delay | 60 | 游客登录限流(秒)✅ |
| — | max-chat-message-length | 320 | 聊天消息长度上限,硬顶 1000 ✅(截断行为) |
| — | channel-path | r | 频道 URL 路径段 ✅ |
| — | channel-blacklist | [] | 频道名黑名单 |
| — | channel-save-interval | 5 | 频道状态保存周期(分钟)✅ |
| aliases | purge-interval / max-age | 3600000 / 2592000000 | 别名清扫周期/保留期(毫秒) |
| — | vimeo-workaround | false | Vimeo 屏蔽兼容 |
| reserved-names | usernames/channels/pagetitles | admin、owner 变形正则 | 保留名规则 ✅(五组对比) |
| playlist | max-items / update-interval | 4000 / 5 | 队列上限 / 进度广播周期(秒)✅ |
| — | aggressive-gc | false | 主动 GC(需 --expose-gc) |
| ffmpeg | enabled / ffprobe-exec | false / ffprobe | 直链视频探测 ✅ |
| — | link-domain-blacklist | [] | 链接域名黑名单 |
| setuid | enabled 等 | false | root 启动降权 |
| service-socket | enabled / socket | false / service.sock | 管理命令套接字 ✅ |
| — | poll.max-options | 50 | 投票选项上限 |
| conf/camo.toml | ([camo]) | 未配置 | 聊天图片代理 ✅(未配置日志) |
| conf/captcha.toml | ([hcaptcha]/[register]) | 未配置 | 注册验证码 ✅(未配置日志) |
| conf/email.toml | ([smtp]/[password-reset]/[delete-account]) | 未配置 | 邮件能力 ✅(未配置日志) |
| conf/prometheus.toml | ([prometheus]) | 未配置 | 指标暴露 ✅(/metrics 回显) |