网站仅在移动设备上加载不一致
Posted
技术标签:
【中文标题】网站仅在移动设备上加载不一致【英文标题】:Website loads inconsistently on mobile only 【发布时间】:2021-10-17 12:59:18 【问题描述】:我有一个通过自定义网络服务器提供服务的网站,当从笔记本电脑/台式机浏览器加载时,它可以正常加载并运行良好,但在移动浏览器上加载不一致。 (就我而言,我专门测试了 android 上的三星 Internet 和 Chrome)
(确切的行为是:加载网页,刷新,然后在几次刷新后它有时将无法加载背景图像或页面上的任何资源 - 但仅限于移动浏览器)
如果这只是一些缓存数据问题,我已清除所有浏览器数据,重新启动手机,请朋友在他们的设备上试用等,但我只能在移动设备上重现此问题。
我的 Web 服务器是使用 liburing
编写的,nginx 作为反向代理,但我怀疑这会是问题
我阅读了Can Anyone Explain These Long Network Stalled Times?,我发现一个问题可能是我使用多个不同的 HTTP 请求来获取资源(我还没有实现 Connection: Keep-Alive
),但我在 WiFi 上也遇到了这个问题,我得到了即使在加载单个资产(例如背景图像)时也会出现问题
其他可能相关的信息:
我最初在桌面上也遇到了类似的问题,我通过在 HTTP 请求上调用close()
之前使用 shutdown()
修复了它
我正在使用以下响应标头:
Keep-Alive: timeout=0, max=0
Connection: close
Cache-Control: no-cache
我正在使用以下套接字选项:
SO_REUSEADDR
(主要是调试方便)
SO_REUSEPORT
(多线程中的套接字绑定并监听同一个端口)
SO_KEEPALIVE
、TCP_KEEPIDLE
、TCP_KEEPINTVL
和 TCP_KEEPCNT
(杀死不活跃的客户)
奇怪的是,我认为重启手机后它会消失一段时间
我尝试不使用 nginx,而是使用 WolfSSL
进行 TLS,但我遇到了同样的问题
我倾向于认为这可能是我在响应中设置的标头的问题(或者可能是我缺少的一些 HTTPS 特定细节?),但我不确定 如果有人想验证问题,这里是实际站点https://servertest.erewhon.xyz/
【问题讨论】:
【参考方案1】:在我看来,您的服务器没有正确关闭 TLS,而只是关闭了底层 TCP 连接。当客户端通过发送适当的关闭通知 TLS 警报(数据包 27)进行正确的 TLS 关闭时,这会导致您的服务器发送 RST(数据包 28)。
此 RST 将导致客户端关闭连接。根据客户端处理传入数据的速度,这可能会导致丢弃 TCP 套接字缓冲区中仍未读取的数据,从而导致您看到的问题。
移动设备和桌面设备之间的行为差异可能只是由系统性能引起的,也可能是由底层 TCP 堆栈引起的。但无论桌面是否正常工作 - 您的网络服务器都会出现问题。
有关如何在 HTTP 级别关闭连接的详细信息,请参阅RFC 7230 section 6.6。特别注意本节的以下部分:
如果服务器立即关闭 TCP 连接,则 客户将无法阅读最后一个的重大风险 HTTP 响应。如果服务器从 客户端处于完全关闭的连接上,例如另一个请求 客户端在收到服务器响应之前发送的, 服务器的 TCP 堆栈将向客户端发送一个重置数据包; 不幸的是,重置数据包可能会擦除客户端的 在读取和解释之前未确认的输入缓冲区 由客户端的 HTTP 解析器。
为避免 TCP 重置问题,服务器通常会关闭连接 分阶段。首先,服务器通过仅关闭来执行半关闭 读/写连接的写端。然后服务器 继续从连接中读取,直到它收到一个 由客户端相应关闭,或直到服务器合理 确定它自己的 TCP 栈已经收到了客户端的 确认包含服务器最后的数据包 回复。最后,服务器完全关闭连接。
【讨论】:
据我了解,这种行为是因为我一写完就立即调用shutdown
然后close
,然后我猜nginx反向代理也会调用shutdown
得到它?你知道如何让 nginx 在不放弃shutdown
的情况下正确关闭(因为这似乎是让它在桌面上工作的唯一方法)
我不知道您的设置,即您是仅使用 HTTP 还是在自定义服务器软件中使用 HTTPS。最好的方法可能是等待关闭读取,直到客户端关闭连接,它应该根据Connection: close
执行此操作。但是客户端只有在读取完整响应后才会这样做。另请参阅更新的答案
谢谢,我记得读过你可以单独关闭读/写,但这完全有道理,它可以解释为什么在不使用 nginx 作为反向代理时甚至会发生这种情况以上是关于网站仅在移动设备上加载不一致的主要内容,如果未能解决你的问题,请参考以下文章