Composer 自建私有 Packagist 不适用 OSS 冷热分级存储策略——packages.json 必须热可用、低延迟、强一致,而 OSS 冷层不支持高频 HEAD/GET、无 ETag 校验、无 HTTP 缓存协商,会导致 Composer 解析失败或静默跳过源。

直接说结论:Composer 自建私有 Packagist **不适用 OSS 冷热分级存储策略**——packages.json 必须热可用、低延迟、强一致,而 OSS 的冷层(如阿里云 IA、腾讯云 STANDARD_IA)不支持高频 HEAD/GET、无 ETag 校验、无 HTTP 缓存协商能力,会导致 Composer 客户端解析失败或静默跳过源。
为什么 packages.json 不能放 OSS 冷层
Composer 在 install/update 前会并发请求 packages.json 和各 provider 文件(如 provider-2023-01.json),并依赖以下行为:
- HTTP 状态码必须是
200,冷层对象首次访问常返回307重定向或延迟数秒才可读,Composer 不跟随重定向且超时默认仅 5s - 必须返回准确的
Content-Length和ETag,OSS 冷层不支持 ETag(返回的是"etag":"null"),导致 Composer 无法做本地缓存比对,反复全量下载 - 文件需支持 Range 请求(用于大 JSON 分片校验),冷层不支持
Range头,packages.json超 4MB 时 Composer 解析直接中断 - PHP 的
file_get_contents()或 cURL 默认不处理 OSS 冷层的取回延迟逻辑,无重试机制
satis build 生成的 dist 包可以进 OSS 冷层,但有条件
dist ZIP/TAR 包是只读、按版本哈希寻址、极少被修改的静态资源,适合下沉到冷层——但必须满足三个硬约束:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- dist URL 必须由 Nginx/Apache 反向代理中转,**不能直接暴露 OSS 域名**;否则 Composer 会尝试用
https://bucket.oss-cn-hangzhou.aliyuncs.com/dist/xxx.zip下载,而 OSS 冷层对象需先调用restoreObjectAPI 才可读,客户端无此能力 - 在
satis.json中显式配置"archive": {"format": "zip", "skip-dev": true},确保生成的 dist 文件名含完整 hash(如acme-utils-1.2.3-zip-abc123.zip),避免冷层对象被覆盖后无法回滚 - OSS Bucket 必须开启
静态网站托管并绑定自定义域名(如dist.internal.company),且该域名需配置在satis.json的"archive": {"url": "https://dist.internal.company/"}中——Composer 只认这个 URL,不认 OSS 原生 endpoint
真正可行的冷热分层架构:Nginx + OSS + TTL 控制
不是把文件“扔进冷层”,而是靠反向代理层做策略路由。关键点在于让热数据走 CDN 缓存,冷数据走 OSS 回源,且对 Composer 完全透明:
- Nginx 配置两级缓存:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=packages:10m max_size=1g inactive=1h;,专用于packages.json和 provider 文件(TTL 300s) - dist ZIP 请求走另一 location,匹配
^/dist/.*\.zip$,proxy_pass 到 OSS 域名,并加proxy_cache_key "$scheme$request_method$host$uri$is_args$args";避免 hash 冲突 - OSS Bucket 设置生命周期规则:dist 对象创建 30 天后转 IA,90 天后转归档;但 Nginx 层必须配置
proxy_next_upstream error timeout http_502 http_503 http_504,当 OSS 返回404(冷层未取回)或503(正在取回)时,自动 fallback 到备用热存储(如 NFS 或另一台 Nginx 挂载的 SSD 盘) - 所有
satis build后,必须运行脚本主动触发 OSS 冷层对象取回(ossutil restore -r oss://bucket/dist/ --tier Standard),否则 CI 流水线里composer install第一次必然失败
最易被忽略的一点:Composer 从不校验 dist 文件的 Content-MD5,哪怕 OSS 归档层解压出错,它也认为下载完成——所以必须在 Nginx 层加 add_header X-OSS-Hash-MD5 $upstream_http_x_oss_hash_md5;,并在 CI 中用 curl 检查该 header 是否存在且非空,否则整个冷层链路就是个单点故障黑洞。

















