一个最简单的 http 服务器:
func main() {
fs := http.FileServer( http.Dir("./public"))
http.Handle("/", fs)
http.ListenAndServe(":8888", nil)
}

用 curl 测试几个连接同时下载:
curl --limit-rate 1k 1.2.3.4:9999/file.zip --output NUL

结果是,只有第一个和第二个连接正常下载,其他的连接处于停滞状态,只有前面的连接下载完了,后面的才能接着下载。
如果把服务器换成 nginx 则多个连接都可以同时下载。
以上都是在 Windows 11 下进行的
Go 的版本是 1.18.1

你就不能在 fs 里面加个 go 么

跟你一样的环境,一样的代码,我测试可以并发下载

抱歉我没看懂,如何在 fs 里面加个 go

我反复多次都是只能两个连接同时下载,我也不知道我哪不对,所有又用了 nginx 试

对不起我错了,http 本来就是协程的

http.ListenAndServe 里面就有 go c.serve(connCtx),不需要 fs 再 go 了吧?

可能说监听队列长度问题。你可以 google 下如何指定。大概率是你 nil 的那个位置。

我猜是写入了同个文件 NUL ?

问题很奇怪,好像和下载的文件大小有关,测试如下:

如果我用小文件(小于 100KB )可以多个同时下载
如果文件大于 1MB 就只能两个同时下载,其他的等待

莫名其妙啊

应该不是 go 的问题,我测试的文件几十 MB ,对了,我 curl 命令是在 wsl 里面执行的

我是打开了四个 cmd 窗口,用 curl 下载,我再试试

不会是 cmd 窗口卡住了吧 :doge

http.DefaultTransport = &http.Transport{
DisableKeepAlives: true,
}
配置下可以,原因未知

用同样的 cmd 窗口,从 nginx 下载就没有问题。

试了 http.DefaultTransport ,也不行。另外我查了 http.DefaultTransport 是用在 client 端的,服务端是用 SetKeepAlivesEnabled(false) ,试了还是不行。

nul 文件锁

浏览器这没复现成功,Chrome windows11 go1.18.1 四个标签页下载,都能正常下载。

go 默认运行在一个 cpu 核上的,尝试设置下 runtime.GOMAXPROCS

不是 NUL 的问题,即使把 NUL 改为不同的文件名,结果同样。

网上可查得 Starting from Go 1.5, the default value of GOMAXPROCS is the number of cores.

我也用 Chrome 试了,连续下载四次,开始时只有前两个下载有进度,后两个下载进度一直显示 0 。
但是过了一会,神奇的事情发生了,第三个下载在一瞬间完成了。又过了一会,第四个也在一瞬间完成了。
而这时,第一个和第二个还在下载中。。。

上面一瞬间完成的下载,找到原因了,是下载出错了,只下载了 1KB ,而原文件是 72MB

我又用 Chrome 反复试了,结论还是只能有两个连接同时下载,后面的连接要等前面的结束后才开始下载。

试了一下还真是,第一个和第二个正常下载,第三个就停住不动,如果结束掉其中一个,第三个就正常下载了

终于能复现了 🤣🤣🤣

我刚刚又试了下,还是没有出现你的问题,同时下载四个 10G 左右的视频。两个视频速度 200mb/s 多,两个视频 50mb/s 左右。其中只有一个视频初始下载速度大概 100B/s 持续了 3 秒左右就正常了。

可我这怎么都不行

用 aria2 测试也是这样, 就算是 aria2 和 curl 混用也不能超过 2 个任务, 不知道为什么

我用 curl 和 chrome 混用也不能超过两个