网速正常但网站打开慢
网速正常但网站打开慢
现象:网络测速 340Mbps,ping 延迟低于 50ms,但是访问 B 站 经常出现白屏、https 超时、数据无法加载、刷新后长时间白屏的问题。
同时,使用 B 站的手机 app 访问,也会出现长时间黑屏、点击点赞按钮后延迟 10 几秒才响应,但是此问题在新版本 B 站客户端中已解决。
另外,访问局域网内自己部署的 web 服务,也会出现 10 几秒的延迟,才能加载页面。
解决手机 app
在路由器上更换 DNS 后访问正常。
解决电脑访问 B 站卡顿
参考为什么我的电脑网速正常 打开网页的速度却很慢?,关闭计算机的 IPv6。
控制面板→网络和共享中心→更改适配器设置→选择当前网络→属性→取消勾选协议版本6→确定
从原理到实践,彻底告别 IPv6 上网不稳定的问题 做了很详细的介绍。
关于 IPv6 为何卡顿:
DNS解析
IPv6的DNS解析速度通常比IPv4慢,尤其是在某些地区或网络环境下,IPv6 DNS服务器的性能不佳可能导致解析延迟。例如,有用户反映在某些地区开启IPv6后,DNS解析速度显著下降,从而影响网页加载速度
PMTU黑洞
IPv6不支持分片,而许多网络设备(如光猫和路由器)对IPv6的优化不足,可能会导致MTU(最大传输单元)设置不当,从而引发数据包丢失或丢弃,进一步影响网分片问题。
家用路由器开启 IPV6, wifi 访问变慢甚至打不开网页?
MTU (Maximum transmission unit) 是一条链路上可以通过的三层数据包的最大尺寸(包含 IP 包头)。以太网上默认的 MTU 是 1500 字节,但是你和目标服务器之间的路径上可能存在小于 MTU 1500 的链路。这条路径上最小的 MTU 值就是整条路径的 PMTU 值。路由器在转发包时,超过 MTU 大小的包会被分片( Fragmentation ),也就是一个大包会被分切为多个不超过 MTU 的小包进行传输,传输效率会下降。
现在国内 ISP 一般都是通过 PPPoE 虚拟拨号建立 WAN 口连接的。Ethernet 的默认 MTU 是 1500,但是 PPPoE 隧道有 8 个 bytes 的开销,所以 PPPoE 虚连接的 MTU 就是 1500-8=1492,减掉 IPv4 包头( 20 字节)和 TCP 包头( 20 字节),可以得知 IPv4 下需要把 MSS 设为 1452 以下。
此文章也表示:目前来看,要想在国内比较理想地体验 IPv6,你需要把光猫改为桥接模式,并使用 OpenWRT 或者 VyOS 这类对 IPv6 支持较好的软路由
双栈技术的切换延迟
现代浏览器通常采用双栈技术(同时支持IPv4和IPv6),但在切换过程中可能会出现短暂的延迟。例如,浏览器会优先尝试通过IPv6访问资源,如果失败则切换到IPv4,这种切换机制可能导致加载时间变长
网站外链
当网页包含指向其他网站内容的链接(外链),而这些外链的服务器尚未升级支持IPv6时,IPv6用户访问这些网页时会出现响应缓慢、部分内容无法显示等问题。
再看问题
2025-03-16 终于在浏览器网络面板抓到了一条超时请求:
Google Chrome 会等待可复用 TCP 连接
在从理解谷歌浏览器timing到优化页面请求阻塞的问题实战上看到:
Stalled:请求在可以被发送出去之前的等待时间(阻塞时间),一般是等待可复用的TCP连接释放的时间。浏览器对于单个域名只能同时建立4~6个TCP连接(不同浏览器实现有差异)。
问题在浏览器底层
谷歌chrome浏览器network中Stalled分析和优化中提到:
Stalled 也即是从 TCP 连接建立完成,到真正可以传输数据之间的时间差。
stalled阶段时TCP连接的检测过程,如果检测成功就会继续使用该TCP连接发送数据,如果检测失败就会重新建立TCP连接。所以出现stalled阶段过长,往往是丢包所致,这也意味着网络或服务端有问题。
根本问题是在于浏览器的底层上,浏览器对同一个主机域名的并发连接数有限制,因此如果当前的连接数已经超过上限,那么其余请求就会被阻塞,等待新的可用连接
解决方案,但不适合
Stalled时间过长导致的网页响应缓慢的排查记录 指出,需要同时改动网页前端和后端,才能缓解问题。
大屏由多个组件构成,每个组件分别调用一个接口,并且是同时调用的。而这些接口由于一些原因响应很慢,一直在Pending状态。这就影响到了同一个浏览器中其它标签页中对同一个域名的请求。
在Some websites take extremely long to load and show stalled in network tab上看到了类似的问题:
但仅一个回答,表示更新网卡驱动到最新即可。
Stackoverflow 上的回答
在Stackoverflow上看到了相同的问题:
I’m trying to implement long polling for the first time, and I’m using XMLHttpRequest objects to do it. So far, I’ve been successful at getting events in Firefox and Internet Explorer 11, but Chrome strangely is the odd one out this time.
I can load one page and it runs just fine. It makes the request right away and starts processing and displaying events. If I open the page in a second tab, one of the pages starts seeing delays in receiving events. In the dev tools window, I see multiple requests with this kind of timing:
回答如下:
Yes, this behavior is due to Chrome locking the cache and waiting to see the result of one request before requesting the same resource again. The answer is to find a way to make the requests unique. I added a random number to the query string, and everything is working now.
For future reference, this was Chrome 39.0.2171.95.
Edit: Since this answer, I’ve come to understand that "Cache-Control: no-cache"
doesn’t do what I thought it does. Despite its name, responses with this header can be cached. I haven’t tried, but I wonder if using “Cache-Control: no-store”, which does prevent caching, would fix the issue.
针对此问题的解决方案:
- 前端请求时,在 URL 后面加上一个随机数,如
https://example.com/api?random=12345
- 后端返回响应头设置
Cache-Control: no-cache, no-store
或者Cache-Control: max-age=3, must-revalidate
结论
问题出在谷歌浏览器的底层,限制了同一个域名的并发连接数,导致请求被阻塞,导致网页响应缓慢。
解决方案:无解。我无法修改 B 站的前后端。