我们在 heroku 上运行 django/gunicorn 服务器。我们的大多数用户所在的国家/地区的移动网络都不是那么好,因此他们的连接经常不稳定。
我们的大多数请求都是来自移动设备的“原始帖子”,似乎即使 POST 请求没有完全传输,请求也已经被发送给 gunicorn worker 处理。当工作人员尝试处理请求并读取数据时,它只是挂起等待剩余的数据。虽然这种行为对于在“流”模式下读取文件/图像数据是有意义的,但在我们的案例中却没有意义,因为我们所有的帖子都相对较小,可以很容易地被整个 Web 服务器读取,然后才转发到我们的 gunicorn工人。
当我们有许多这样的并行请求时,这种早期切换会导致麻烦——因为所有工作人员都可能被阻塞。目前,我们通过增加工人/测功机的数量来解决这个问题,但这非常昂贵。我找不到任何方法来强制 Web 服务器或 gunicorn 等待,并且只有在请求完全传输后才将请求转发给工作人员。
有没有办法让heroku的Web服务器/gunicorn仅在客户端完全传输请求(服务器完全接收)时才将请求传输给gunicorn工作者?
一些示例代码(我们添加了 newrelic 'per-instruction' tracking 以确保这是导致问题的确切行):
def syncGameState(request):
transaction = agent.current_transaction()
with agent.FunctionTrace(transaction, "syncGameState_raw_post_data", 'Python/EndPoint'):
data = request.raw_post_data
with agent.FunctionTrace(transaction, "syncGameState_gameStateSyncRequest", 'Python/EndPoint'):
sync_request = sync_pb2.gameStateSyncRequest()
with agent.FunctionTrace(transaction, "syncGameState_ParseFromString", 'Python/EndPoint'):
sync_request.ParseFromString(data)
这是此示例慢速请求的 New Relic 测量结果(它是一个包含 7K 数据的 POST)。读取 POST 需要 99% 的方法时间....