composer客户端不支持quic,硬上会fallback至http/1.1;可行方案是用caddy/nginx+quiche终结http/3,后端quic-go仅服务自研下载器,并需严格配置alpn、tls 1.3、udp端口及流参数。

用 quic-go 搭建 Composer 镜像传输通道,不是简单替换 http.Server 就能跑通的——它必须绕过 PHP 的 cURL 限制、适配 Packagist 的语义约束、并解决 Composer 客户端对 ALPN 和 Alt-Svc 的静默忽略问题。
Composer 客户端根本不支持 QUIC,硬上会直接 fallback 到 HTTP/1.1
Composer(截至 2.7.x)底层使用 PHP 的 cURL 扩展发起请求,而 cURL 目前(2026 年中)仍不支持 QUIC 或 HTTP/3。即使你用 quic-go + http3.Server 跑起服务,Composer 发出的请求仍走 TCP+TLS 1.2/1.3,根本不会协商 h3 ALPN。这不是配置问题,是客户端能力缺失。
- 验证方式:抓包看 ClientHello 中
ALPN扩展是否含"h3";实际抓包几乎总是只有"http/1.1"和"h2" - 替代路径只有两条:改 Composer 源码换掉 cURL(不现实),或在反向代理层做协议转换
- 生产中真正可行的做法是:用 Caddy 或 Nginx+quiche 做前端 HTTP/3 终结,后端用
quic-go提供纯 QUIC 流式文件服务,但只暴露给自研下载器或 CLI 工具,不指望 Composer 直连
quic-go 服务端必须显式支持 Packagist 的流式分发模式
Composer 镜像不是静态文件托管,而是动态响应 /packages.json、/p/<vendor>.json</vendor>、/dist/xxx.zip 等路径,且大量依赖 Range 请求和 302 重定向。QUIC 的流模型天然适合分块传输,但默认配置会卡死:
-
MaxIncomingStreams必须设为 ≥500:Packagist 单次composer update可能并发拉取数十个包元数据 + 几个 dist 文件,每个都是独立 stream - 禁用
StreamIdleTimeout或设为 ≥30s:PHP 进程解析packages.json后再发 dist 请求有延迟,QUIC 默认 30s idle timeout 会导致 stream 被 server 主动关闭 - 务必实现
http3.ResponseController接口中的SetWriteDeadline:否则大 dist 文件(如 Laravel 的 10MB zip)在弱网下易因 WriteDeadline 触发stream reset
证书与 ALPN 配置错一个字,客户端就看不到 h3
quic-go 对 TLS 配置极其敏感,尤其 NextProtos 字段必须精确为 []string{"h3"},多空格、大小写错、顺序错(比如 ["h3", "h2"])都会导致 ALPN 协商失败,浏览器或 curl -v 显示 no application protocol negotiated。
- 证书不能仅含域名,必须带 SAN(Subject Alternative Name),且匹配请求 Host;自签名证书需用
openssl req -addext "subjectAltName = DNS:repo.example.com"生成 -
tls.Config中不能漏掉MinVersion: tls.VersionTLS13:QUIC 强制要求 TLS 1.3,低于此版本会静默拒绝连接 - 启动监听必须用
quic.ListenAddr,而非http3.ListenAndServe—— 后者内部调用前者但封装了错误处理,掩盖真实 TLS 错误
UDP 端口和防火墙是线上最常被忽略的环节
HTTP/3 默认走 UDP 443,但绝大多数云厂商安全组、K8s Service、甚至宿主机 iptables 默认**只放行 TCP 443**。QUIC 连接会在三次握手后立刻失败,且无明确错误日志,表现为“连接超时”或“ERR_QUIC_PROTOCOL_ERROR”。
- 检查命令:
sudo ss -ulnp | grep :443确认进程确实在监听 UDP,而非仅 TCP - 阿里云/腾讯云需单独添加 UDP 443 入方向规则;AWS Security Group 同理,Protocol 选 UDP
- Kubernetes Ingress Controller(如 ingress-nginx)不支持 QUIC,必须用 LoadBalancer Service 直通 Pod,或改用 Caddy Ingress
真正落地时,最棘手的不是代码,而是让整个链路的每个环节都“知道 QUIC 在跑”——从客户端 DNS 解析是否返回 HTTPS RR 记录,到中间 CDN 是否透传 UDP,再到终端操作系统是否启用 QUIC 栈(Windows 11 22H2+、Linux kernel ≥5.13)。少一环,就退回 TCP。











