前言
6 月底从外网往家里的 Nextcloud 传文件时,发现上传速度特别慢。家里这套服务的入口是 Caddy 容器,外网请求先连到 Caddy,再反向代理给后端的 Nextcloud 容器。
排查时先把 Caddy 默认开启的 HTTP/3 关掉、只保留 HTTP/1.1 和 HTTP/2,改完之后上传速度明显好转,能稳定跑到 3M 左右;后面又顺手看了一眼 Linux 内核参数,把默认的 TCP 拥塞控制从 cubic 切到了 bbr。这篇笔记把当时改过的配置和排查思路整理一下,方便以后再遇到类似问题时按步骤定位。
上传链路分析
在网页或者客户端里点上传,数据大概要走完这么一串流程:
客户端读取本地文件
↓
外网 / VPN 传输
↓
Caddy 监听端口并处理 TLS
↓
转发给 Nextcloud 容器
↓
写入临时目录、分块合并、落盘存储进度条走得慢,可能是网络传输本身卡,也可能是最后文件分块合并、写硬盘的时候卡。动手改配置前,最好先看清现象:
- 是内网和外网一起慢,还是只有走外网/VPN 的时候慢?
- 是从头到尾速度都很低,还是前面跑得挺快、到了最后 99% 卡半天?
- 是传单个大文件慢,还是传几百个零碎小文件慢?
如果想对比改配置前后的效果,最好固定拿同一个大文件在相同网络下来回测,不要一会儿传照片、一会儿传压缩包。
调整 Caddy HTTP 协议配置
当时做的第一个改动,是在 Caddy 的全局配置里限制了 HTTP 协议版本,只保留 HTTP/1.1 和 HTTP/2,关掉了走 UDP 的 HTTP/3(QUIC):
{
servers {
protocols h1 h2
}
}这段配置加在 /etc/caddy/Caddyfile 最顶部的全局大括号里就行,原本配好的域名、证书和反代规则不用动(参数含义见 Caddy 全局选项文档)。
改完之后先检查一下语法,没问题再重载 Caddy:
podman exec caddy caddy validate --config /etc/caddy/Caddyfile
podman exec caddy caddy reload --config /etc/caddy/Caddyfile提示
提示 重载配置后测试时,建议在浏览器里开无痕窗口或者打开开发者工具(F12)看一眼 Network 面板里的 Protocol 列,确认请求确实走的是
h2,避免浏览器还复用着之前的旧连接。
不少跨网环境对 UDP 流量(HTTP/3 底层使用的 QUIC)不太友好,容易遇到限速或丢包,切回基于 TCP 的 HTTP/2 往往更稳。当时改完配置重载后,上传速度就恢复到了 3M 左右;如果想确认是不是 HTTP/3 拖慢了速度,单独开关 protocols h1 h2 对比测一次就能看出来。
上传大小限制与传输速率
网上一搜 Nextcloud 上传优化,很多教程上来就让人把请求体上限、PHP 限制和超时时间全改成无限大。其实这两件事要分开看:
- 传大文件传到一半直接报错失败:这才是触发了体积上限或者超时限制,需要去查 Caddy、PHP 和 Nextcloud 的大文件分块配置(参考 Nextcloud 大文件上传文档)。
- 没有报错,但速度一直只有几百 KB:把大小限制改成无限并不会让网速变快,还是得从网络协议、反代缓冲或者硬盘读写上找原因。
配置服务端 TCP BBR
看到改完 Caddy 有效果后,我又顺手看了一眼服务器的 TCP 拥塞控制参数。当时默认的输出是:
net.ipv4.tcp_congestion_control = cubic
net.core.default_qdisc = fq_codel
net.ipv4.tcp_available_congestion_control = reno cubic接着我加载了 tcp_bbr 模块,并临时把队列算法和拥塞控制切到了 fq 和 bbr:
sudo modprobe tcp_bbr
sysctl net.ipv4.tcp_available_congestion_control
sudo sysctl -w net.core.default_qdisc=fq
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr跑完之后再查 sysctl,确认已经变成了 bbr 和 fq(参数说明见 Linux TCP sysctl 文档)。需要注意,sysctl -w 只是临时生效,确认没问题后还要写进 /etc/sysctl.d/ 下的配置文件里,重启服务器才不会恢复默认。
重要
为什么服务器开 BBR 对“上传”不一定管用? 后来仔细想了一下才反应过来:TCP 拥塞控制主要管的是发送方怎么发包。 从外网往家里 Nextcloud 下载文件时,服务器是发送方,开 BBR 确实能改善高延迟或轻微丢包下的发送速度;但上传文件时,发包的主力是外面的客户端(电脑或手机),服务器只是接收方。所以服务器开 BBR 并不能替客户端改变它的上传发包策略。
服务端状态排查命令
如果以后再遇到 Nextcloud 传文件卡顿,可以先在服务器上跑这几条命令看看资源和连接状态:
podman stats --no-stream
df -h
journalctl --user -u caddy.service -b -n 100 --no-pager
ss -ti- 看
podman stats和df -h:排除是不是容器内存爆了,或者临时目录所在的硬盘空间满了。 - 看
journalctl和 Nextcloud 日志:找刚巧发生在上传卡住那一分钟的报错,别被几天前的旧报错误导。 - 每次只改一个地方:比如先单测 HTTP/2 和 HTTP/3 的区别,测完再动别的参数,这样才能搞清楚到底是谁在拖后腿。