传播http abort /关闭从nginx到uwsgi / Django如何实现?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (154)

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

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

转到uwsgi_ignore_client_abort“on”只会让nginx不知道中止/关闭,并移除uwsgi“IO Errors”,因为uwsgi仍然可以写回到nginx。

我的用例是我有一个应用程序,用户可以非常快速地浏览一些ajax结果,所以如果通过快速页面中止他们跳过的页面的挂起的ajax请求,这可以使客户端保持清洁和高效。但是这对服务器端(uwsgi / Django)没有任何作用,因为即使没有任何东西会等待响应,他们仍然需要处理每一个请求。

现在显然可能会有某些页面,我不希望请求因任何原因过早中止。但是我使用celery来处理可能属于该类别的长时间运行的请求。

这可能吗?uwsgi'shariakari设置让我觉得它在某种程度上......只是无法弄清楚如何去做。

提问于
用户回答回答于

现在显然可能会有某些页面,我不希望请求因任何原因过早中止。

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

  • 显然,可能不想继续花费系统资源来处理已经中止的连接,例如昂贵的搜索操作。
  • 但是,也许连接是非常重要的,即使客户端已经断开连接仍然需要处理。
    • 例如,非常昂贵的搜索操作,但实际上并非特定于客户端的搜索操作,并且也将由nginx为所有后续客户端缓存。
    • 或者可能是修改应用程序状态的操作 - 显然不希望让应用程序出现不一致的状态!

如前所述,问题出在uWSGI上,而不是在NGINX上。然而,你不能让uWSGI自动决定你的意图,没有你自己向uWSGI透露这样的意图。

你将如何在你的代码中揭示你的意图?一大堆编程语言并不真正支持多线程和/或异步编程模型,这使得取消操作变得完全不重要。

因此,这里没有神奇的解决方案。 即使像Golang这样的并发友好的编程语言也存在一些问题WithCancel context - 你可能不得不在每一个可能阻塞的函数调用中传递它,使得代码非常难看。

是否已经在Django中传递上述上下文?如果不是,那么解决方案很难但非常简单 - 只要您明确放弃请求,就可以检查客户端是否仍然连接uwsgi.is_connected(uwsgi.connection_fd())

用户回答回答于

我的用例是我有一个应用程序,用户可以非常快速地浏览一些ajax结果,所以如果通过快速页面中止他们跳过的页面的挂起的ajax请求,这可以使客户端保持清洁和高效。

通过在客户端中止AJAX请求XMLHttpRequest.abort()。如果请求在abort()被调用时尚未发出,则该请求不会熄灭。但是,如果请求已发送,服务器将不知道该请求已被中止。连接不会关闭,不会有任何消息发送到服务器,什么都不是。如果希望服务器知道不再需要某个请求,则基本上需要提供一种识别请求的方法,以便在发出初始请求时获得该请求的标识符。然后,通过另一个AJAX请求,您告诉服务器应该取消先前的请求。

请注意,uwsgi_ignore_client_abort这是处理TCP级别的连接关闭的事情。这与放弃AJAX请求完全不同。在JavaScript中通常不会采取任何行动,这将导致关闭TCP连接。浏览器优化连接的创建和销毁以适应其需求。刚才,我这样做了:

  1. 我曾经lsof检查过程是否有连接example.com。没有。(lsof是允许列出打开文件的* nix工具,网络连接是* nix中的“文件”)。
  2. 我在Chrome中打开了一个页面到example.com。lsof显示了连接和打开它的过程。
  3. 然后我关闭了页面。
  4. 我询问了一下lsof,看看我之前确定的连接是否仍然打开。即使没有真正需要保持连接打开,我在关闭页面后仍保持打开状态约一分钟。

而且没有太多的uswgi设置的摆弄,这将使它意识到通过执行中止 XMLHttpRequest.abort()

你提供的用例场景是用户通过某些结果进行快速分页的场景。我可以看到在问题中给出的描述有两种可能性:

  1. 用户在进一步分页之前等待刷新。例如,Alice正在浏览按字母顺序排列的用户名“Zeno”的用户名列表,每次显示一个新页面时,她都会看到该名称不存在且页面向下。在这种情况下,没有什么可放弃的,因为用户的操作取决于首先处理的请求。(用户在做决定之前必须看到新的页面。)
  2. 用户只是在不等待刷新的情况下向下翻页。在这种情况下,可以消除对服务器发出的请求。然后按下下一页按钮,递增应向用户显示的页面数量,但不要立即发送请求。相反,在用户停止点击该按钮之后等待一小段延迟,然后用最终页码发送请求,因此您发出一个请求而不是一打。

扫码关注云+社区

领取腾讯云代金券