satis 本身不能高可用,所谓“高可用”是静态文件 + 基础设施层的组合结果——必须集中构建、原子同步、共享存储挂载、nginx 健康探活四者齐备,缺一不可。

直接说结论:Satis 本身不能高可用,所谓“高可用”是静态文件 + 基础设施层的组合结果——必须集中构建、原子同步、共享存储挂载、Nginx 健康探活四者齐备,缺一不可。
为什么 satis build 不能加负载均衡节点
Satis 是一次性进程,不是常驻服务:不监听端口、不维持连接、不响应 HTTP 请求。你起 10 台机器并发跑 php bin/satis build,每台都独立输出一份 packages.json 和 dist/,但内容可能因 Git 凭据差异、tag 解析顺序、时区或 PHP 版本不同而错位。
- CI 流水线里并发触发多节点构建 → 各节点
packages.json的dist.url指向本地路径,其他节点根本找不到 ZIP - 没共享存储,只靠
rsync推送 → 存在窗口期,某节点刚写完一半packages.json就被 Nginx 读到半截文件 -
satis build进程退出后无法健康探测 → Nginx upstream 无法识别它是否“活着”,只能靠下游请求失败被动剔除
共享存储必须挂载,不能只靠 rsync 同步
所有 Nginx 节点的 root 必须指向同一份物理文件。用 NFS、MinIO 或 S3 挂载 /var/www/satis/web,比定时 rsync 可靠得多。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- NFS 挂载后,
mv替换整个web/目录才是原子操作;rsync --delete-after仍存在短暂不一致 - 若用对象存储(如 MinIO),需确保 Nginx 静态路由能透传
/dist/xxx.zip到对应 bucket,且Content-Type正确(application/zip) - 所有节点禁用 PHP 解析、目录权限设为
read-only,防止上传恶意文件覆盖packages.json
Nginx upstream 健康检查必须精准有效
只写 upstream satis { server 10.0.1.10; server 10.0.1.11; } 没用。Composer 并发短连接会随机打到宕机节点,卡在 Downloading (connecting)。
- 启用
max_fails=2 fail_timeout=30s,避免网络抖动误判 - 用
location = /packages.json作探针:轻量、可缓存、真实反映文件可读性 - 显式声明
types { application/json json; },否则返回text/plain时 Composer 解析失败但 HTTP 状态码仍是 200,上游不会被踢出 - 禁用
ip_hash:Composer 请求无粘性,会导致流量倾斜
dist URL 填错一个字符就会全链路卡死
"archive": {"prefix-url": "https://cdn.example.com/dist/"} 这行看着简单,但填错就导致所有私有包 --prefer-dist 失效。
- 必须以
/dist/结尾(注意末尾斜杠),否则生成的 ZIP URL 变成https://cdn.example.comdist/xxx.zip - 该域名必须能被 CI 构建容器、Docker 宿主机、GitLab Runner 等环境 DNS 解析并直连 ——
localhost、未配/etc/hosts的短域名、仅浏览器可达的内网地址都不行 - CDN 或对象存储必须开启 CORS:
Access-Control-Allow-Origin: *,否则Docker-in-Docker场景会因跨域拒绝下载
最易被忽略的是:所有节点的 packages.json 内容一致性,不是“看起来一样”,而是 SHA256 校验一致;以及 homepage 字段和实际可访问 URL 的末尾斜杠必须严格对齐 —— 差一个 /,dist.url 就拼错。










