Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python django的员工在heroku上运行时,当客户的联系不牢固时,他们会挂职_Python_Django_Post_Heroku_Gunicorn - Fatal编程技术网

Python django的员工在heroku上运行时,当客户的联系不牢固时,他们会挂职

Python django的员工在heroku上运行时,当客户的联系不牢固时,他们会挂职,python,django,post,heroku,gunicorn,Python,Django,Post,Heroku,Gunicorn,我们正在heroku上运行django/gunicorn服务器。我们的大多数用户都在一个移动网络不是很好的国家,所以他们经常有不稳定的连接 我们的大多数请求都是来自移动设备的“原始帖子”,即使帖子请求没有完全传输,请求似乎已经被发送给gunicorn员工处理。当worker试图处理请求并读取数据时,它只是挂起等待剩余的数据。虽然这种行为对于以“流”模式读取文件/图像数据是有意义的,但在我们的案例中没有意义,因为我们所有的帖子都相对较小,整个web服务器很容易读取,然后才转发给我们的gunicor

我们正在heroku上运行django/gunicorn服务器。我们的大多数用户都在一个移动网络不是很好的国家,所以他们经常有不稳定的连接

我们的大多数请求都是来自移动设备的“原始帖子”,即使帖子请求没有完全传输,请求似乎已经被发送给gunicorn员工处理。当worker试图处理请求并读取数据时,它只是挂起等待剩余的数据。虽然这种行为对于以“流”模式读取文件/图像数据是有意义的,但在我们的案例中没有意义,因为我们所有的帖子都相对较小,整个web服务器很容易读取,然后才转发给我们的gunicorn工作人员

当我们同时有许多这样的请求时,这种提前切换会造成麻烦,因为所有的工作人员都可能被阻止。目前,我们通过增加工人/dynos的数量来解决这个问题,但成本相当高。我找不到任何方法强迫web服务器或gunicorn等待,只有在请求完全传输后才将其转发给工作者

有没有办法使heroku的web服务器/gunicorn仅在请求从客户端完全传输(服务器完全接收)后才将请求传输给gunicorn工作者

一些示例代码(我们添加了newrelic“每条指令”跟踪,以确保这正是导致问题的那一行):

下面是这个示例慢速请求(这是一篇包含7K数据的帖子)的最新测量结果。阅读文章需要99%的时间


在我看来,这里的真正问题是gunicorn正在阻止。这是因为gunicorn(默认情况下)使用同步工作进程来运行任务。这意味着,当一个web请求点击gunicorn时,它将被阻止,直到它返回一个响应——在您的例子中,这是一段很长的时间

为了解决这个问题,您可以使用gevent和gunicorn来执行非阻塞IO。由于您的大部分时间都花在IO上,这将确保gunicorn能够并行处理更多的web请求


要将gevent与gunicorn一起使用,您需要安装gevent(
pip install-U gevent
),并通过添加:
gunicorn-k gevent
(这将告诉gunicorn使用gevent作为工作进程)来更改gunicorn启动命令。

并调查缓冲HTTP服务器(如waitess)的请求

我认为heroku的超时时间是10秒。我不打算测试它,但也许您可以在以下位置进行更改:
web:gunicorn hellodjango.wsgi-t3-b0.0.0:$PORT
默认为30秒。我们已经在gunicorn中设置了超时。。。但问题是,在这种情况下,我会取消请求,否则(即使在20秒后)会成功,我真的不想这样做。我想做的是在请求通过网络传输时不要阻止我的工作人员。我对你的帖子感到困惑。当你谈论员工时,你谈论的是“网络动态”还是“员工动态”传输数据时不应锁定Worker dyno,因为收集数据的是“web dyno”。不是吗?(还有,请你告诉我那个慢国家是什么?)我说的是gunicorn的工人。有多个dyno,每个dyno上都有一个gunicorn正在运行,但它通常会生成多个具有-w选项的worker:。在我的情况下,我现在将其设置为-w 12。这些是独立的过程(gunicorn的子进程)。每个路由到特定dyno的请求都通过gunicorn路由到它的一个工作人员。而且,在接收到处理请求后,工作进程在读取数据时(在读取raw_post_数据属性时)似乎处于“保持”状态。也许您可以在raw_post数据分配之前设置一个警报,并在分配结束时禁用它。超时信号是一个简单的SIGTERM信号。我认为它确实是正确的方向(但不完全正确),但走这条路线会使应用程序更加复杂。我必须将请求读取过程(从请求中获取post数据)与请求处理分开。这将允许运行更多的并行读取线程(不需要太多内存)和少量的处理进程。您建议的默认设置实际上不会提供这种功能,因为当我有相同的进程从post读取并处理它时,我也有相同的问题(我不能将进程的数量增加太多)
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)