提问者:小点点

将http中止/关闭从nginx传播到uwsgi/Django


我有一个Django应用程序web应用程序,我想知道nginx是否可以将abort/close传播到uwsgi/Django。

基本上,我知道nginx知道过早中止/关闭,因为它默认为uwsgi_ignore_client_abort关闭,当请求在响应发送前中止/关闭时,你会在nginx日志中得到nginx 499错误。一旦uwsgi完成处理请求,当它返回到nginx的响应时,它会抛出一个“IO错误”。

uwsgi\u ignore\u client\u abort设置为“开”只会使nginx不知道中止/关闭,并删除uwsgi“IO错误”,因为uwsgi仍然可以写回nginx。

我的用例是,我有一个应用程序,其中人们可以快速浏览一些ajax结果,因此,如果快速浏览页面,我将中止他们跳过的页面的挂起ajax请求,这将保持客户机干净高效。但是这对服务器端(uwsgi/Django)没有任何作用,因为即使没有任何东西等待响应,它们仍然必须处理每个请求。

现在很明显,可能有某些页面,我不希望请求因任何原因而过早中止。但是我使用芹菜来处理可能属于这一类的长时间运行的请求。

那么这可能吗?uwsgi的hariakari设置让我认为它在某种程度上......只是不知道如何做到这一点。


共2个答案

匿名用户

我的用例是,我有一个应用程序,其中人们可以快速浏览一些ajax结果,因此,如果快速浏览页面,我将中止他们跳过的页面的挂起ajax请求,这将保持客户机干净高效。

在客户端中止AJAX请求是通过XMLHttpRequest完成的。中止()。如果调用abort()时请求尚未发出,则请求不会发出。但是,如果请求已发送,服务器将不知道请求已中止。连接不会被关闭,不会有任何消息发送到服务器,什么也没有。如果希望服务器知道不再需要某个请求,则基本上需要找到一种方法来识别请求,以便在发出初始请求时获得该请求的标识符。然后,通过另一个AJAX请求,您可以告诉服务器应该取消先前的请求。(如果你搜索关于abort()的问题,比如这个问题,然后搜索“server”,你会找到与此相同的解释。)

请注意,uwsgi\u ignore\u client\u abort是在TCP级别处理连接关闭的功能。这与中止AJAX请求不同。在JavaScript中,通常没有需要关闭TCP连接的操作。浏览器优化连接的创建和销毁以满足其需要。刚才我是这样做的:

>

  • 我使用lsof检查是否有任何进程连接到示例。com。没有。(lsof是一个*nix实用程序,允许列出打开的文件。网络连接是*nix中的“文件”。)

    我打开了一页来举个例子。com在Chrome中lsof显示了连接和打开连接的进程。

    然后我关闭了页面。

    我用lsof进行了轮询,以查看我之前标识的连接是否仍然打开。在我关闭页面后,它保持了大约一分钟的打开状态,即使没有必要保持连接打开。

    而且,不需要再修改uswgi设置,就可以知道通过XMLHttpRequest执行的中止。中止()

    您给出的用例场景是用户通过一些结果快速分页的场景。对于问题中的描述,我可以看到两种可能性:

    >

  • 用户在进一步分页之前等待刷新。例如,爱丽丝正在浏览一个按字母顺序为用户“芝诺”排序的用户名列表,每次显示一个新页面时,她都会看到名称不在那里,页面向下。在这种情况下,没有什么要中止的,因为用户的操作依赖于首先处理的请求。(用户必须在做出决定之前看到新页面。)

    用户只需向下翻页,无需等待刷新。爱丽丝又在找“芝诺”,但她想它会出现在最后一页,所以点击,点击,点击她就去了。在这种情况下,您可以取消对服务器的请求。然后按下下一页按钮,增加应该显示给用户的页数,但不要立即发送请求。相反,在用户停止单击按钮后,您会等待一个小的延迟,然后发送带有最终页码的请求,因此您会发出一个请求,而不是一打请求。下面是为DataTables搜索执行的去盎司的示例。

  • 匿名用户

    现在很明显,可能有某些页面,我不希望由于任何原因导致请求过早中止。

    这正是采取这种或那种方式背后的问题。

    >

  • 显然,您可能不想继续花费系统资源来处理已经中止的连接,例如,昂贵的搜索操作。

    但是,可能连接非常重要,即使客户端断开连接,也必须对其进行处理。

    >

  • 例如,同样昂贵的搜索操作,但实际上不是特定于客户端的,并且将由nginx为所有后续客户端缓存。

    或者可能是修改应用程序状态的操作—您显然不希望应用程序的状态不一致!

    如前所述,问题在于uWSGI,而不是NGINX。然而,如果你不亲自向uWSGI透露你的意图,你就不能让uWSGI自动决定你的意图。

    您将如何在代码中准确地揭示您的意图?许多编程语言并不真正支持多线程和/或异步编程模型,这使得取消操作非常重要。

    因此,这里没有神奇的解决方案。甚至像Golang这样的并发友好编程语言也在Cancel的上下文方面存在问题-您可能必须在每个可能阻塞的函数调用中传递它,这使得代码非常难看。

    您是否已经在Django中传递了上述上下文?如果没有,那么解决方案很难看,但非常简单-任何时候都可以明确中止请求,检查客户端是否仍然与uwsgi连接。是否已连接(uwsgi.connection\u fd())

    • http://lists.unbit.it/pipermail/uwsgi/2013-February/005362.html