首页 > 解决方案 > 如何处理长时间运行的服务器响应和将其视为停止连接的负载均衡器

问题描述

案例/假设:

  1. 有一个服务器是别人写的。
  2. 该服务器有一个端点GET /api/watch
  3. 这个端点是普通的 HTTP/1.1
  4. 该端点将写入事件,例如
    {type:"foo", message:"bar"}
    
    响应流一旦出现(每行一个事件,然后刷新)。
  5. 有时此服务器每秒将事件写入输出,有时每 15 分钟一次。
  6. 在我的客户端和此服务器之间有一个第三方负载均衡器,如果超过 60 秒没有对连接执行任何操作,则该连接假定连接过时,并在不关闭连接的情况下断开连接。
  7. 客户端是用简单的 Golang 编写的,只需向该端点发出 GET 请求。
  8. 一旦连接被 LB 标记为过时,客户端(也发生同样的情况curl)不会通知连接已被 LB 丢弃,并且仍在等待接收 GET 请求响应中的内容。

那么:我有什么可能处理这种情况?

什么是不可能的:

  1. 修改服务器。
  2. 使用另一台服务器。
  3. 使用除此端点之外的其他东西以及它的编写方式。
  4. 修改负载均衡器。
  5. 使用另一个 LB。
  6. 让 LB 脱离连接。

标签: gorequestconnectiontimeout

解决方案


15 分钟对于基本的 HTTP 来说是一个非常长的安静期——可能更适合 WebSockets。如果没有协议更改,您应该能够调整负载均衡器上的超时时间(很难说,因为您没有指定 LB 是什么)以更好地适应您的用例,尽管并非所有负载均衡器都允许超时最高15分钟。如果您无法更改协议并且无法将超时设置得足够高,那么您将不得不每隔一段时间从服务器发送 keepalive 消息(只是超时时间短,因此您当前的配置可能需要 55 秒,或者略小于您可以在 LB 上设置的最高超时时间)。这必须是客户知道要丢弃的东西,比如{"type": "keepalive"}- 在客户端很容易识别为保持活动目的的“假”消息。


推荐阅读