【问题标题】: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/

【问题讨论】:

    标签: sockets http mobile https webserver


    【解决方案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 作为反向代理时甚至会发生这种情况
    猜你喜欢
    • 1970-01-01
    • 2021-10-16
    • 2016-03-08
    • 2015-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多