@
daoqiongsi1101 所以啊,你只要想一想,你 10 个 goroutine 请求是同时请求的,还是有先后顺序的?肯定是同时的啊。
实际上,同时并发请求数受到操作系统的限制(端口数、ulimit 、maxfiles 之类的),为了避免达到操作系统限制,同时降低建立 TCP 的开销,所以浏览器才会实现较小的并发限制。
实际上,具体是看你 golang 代码怎么写的。多个 goroutine 是用的同一个 http.Client 还是不同的,单域名连接数配置的多少。
如果是使用默认的 http.Client 来请求的话,那么走的就是默认的 http.Transport 配置,里面指定的单域名连接数 MaxConnsPerHost 默认是 0 ,也就是不限制。那么你只要没有达到操作系统限制,并发就是能建立多少 TCP 就建立多少 TCP 来并发请求,所以 10 个 goroutine 就是 10 个 TCP 。
而另外,可以针对单个 http.Client 对象来限制连接数,那么使用同一个实例来请求就会受到限制,达到限制就会阻塞等待。
另外注意,这个连接数跟连接池关系不大。默认的 http.Transport 的连接池有两个配置:全部连接池大小 MaxIdleConns 默认是 100 、单域名连接池大小 DefaultMaxIdleConnsPerHost 默认是 2 。这两个配置不影响并发请求的 TCP 连接数。
假设现在是单域名,单域名连接池大小 DefaultMaxIdleConnsPerHost 是 2 ,MaxConnsPerHost 并发数设置了 5 。那么此时你开了 10 个 goroutine 并发,并且每个请求都是 1 秒响应,则会发生这样的情况(实际情况可能受各种竞争因素影响):
1 ,建立 5 个 TCP 连接并发,剩余 5 个连接阻塞等待。
2 ,5 个连接请求结束,只有 2 个 TCP 连接进入连接池复用,剩余 3 个 TCP 连接被 close 。
3 ,剩下的 5 个连接开始请求,其中 2 个复用之前连接池中的 TCP 连接,另外 3 个则建立新的 TCP 连接进行请求。
4 ,所有请求都结束,连接池中持有 2 个连接等待复用,其余连接都被 close 。
5 ,如果没有更多请求了,则连接池中的连接在超时( IdleConnTimeout )后被自动 close 。或者等待 TCP 自己的 keepalive 超时规则( tcp_keepalive_time 、tcp_keepalive_intvl 、tcp_keepalive_probes )来关闭连接。