【问题标题】:Requests not responding on long wait from other IP rather than localhost来自其他 IP 而不是 localhost 的长时间等待请求没有响应
【发布时间】:2018-04-15 01:00:58
【问题描述】:

我应该向我们的 rest url 提出一个 get 请求,这会触发服务器上的一些活动并最终返回一个响应。返回响应可能需要 30 分钟以上。我知道请求没有默认超时。但是,当我提出一个获取请求并且 30 分钟后即使服务器发回响应,请求也没有返回。我确认服务器从日志文件发送了响应。我什至尝试使用请求会话,以便我的连接保持有效。它的行为仍然相同。我正在使用requests v.2.13.0. 是版本问题还是请求问题。如果请求有问题,我如何提出等待服务器发回响应的获取请求?代码很简单,我要添加以供参考。

import requests
url="www.abcd/efg/hijkl"
response=requests.get(url) #It hangs at this point even if server sends back response.

我已经使用邮递员和谷歌浏览器进行了相同的测试,两者都能够在 30 分钟后得到响应。通过将请求更新为2.18.4 也尝试了相同的问题。

编辑 1:

如果从服务器向 localhost 发出请求,则相同的代码可以正常工作。根据@randomir 的建议,network connection might getting dropped inbetween 似乎有问题,但是如何从客户端处理这个问题,因为很难实现任何服务器端方法。

【问题讨论】:

  • "... even if server sends back response." 你怎么知道它有作用?
  • 我用我的服务器日志文件确认了这一点。我想我已经在我的问题中添加了这一点。
  • 唯一可靠的方法是让应用程序级保持活动状态(服务器每隔 n 秒向客户端写一些内容),并在客户端使用读取超时。您的连接可能会在网络层断开。您可以尝试设置 TCP keep-alive。
  • 你可以试试requests toolbeltTCPKeepAliveAdapter吗?

标签: python python-2.7 python-3.x python-requests


【解决方案1】:

您的长期零活动网络连接可能会被中间代理、防火墙、路由器、NAT 等断开。requests.get() 永远不会发现它,因为它被动地等待响应。

在 TCP 层上防止这种情况的一种方法是使用TCP keep-alive(默认情况下通常关闭)。

在 Python 中,您可以直接通过低级 socket.setsockopt 配置 TCP keep-alive,但由于您已经在使用 requests,因此更简单的方法是通过 TCPKeepAliveAdapter 可从 requests_toolbelt 包中获得:

import requests
from requests_toolbelt.adapters.socket_options import TCPKeepAliveAdapter

url = '...'
session = requests.Session()
keep_alive = TCPKeepAliveAdapter(idle=120, count=20, interval=30)
session.mount(url, keep_alive)
session.get(url)

【讨论】:

  • requests.session()中的keep-alive有什么不同?
  • 那是HTTP keep-alive,一种将单个 TCP 连接重用于多个 HTTP 请求的机制。 TCP keep-alive 是较低级别的,适用于传输层,而不是应用层。
  • 顺便说一句,HTTP keep-alive 的工作原理是客户端发送Connection: Keep-alive 头字段,指示服务器在发送响应后不要关闭TCP 连接;从而使客户端能够通过同一个套接字发送另一个 HTTP 请求。 TCP keep-alive 是一个完全不同的野兽,它发送“空”(keep-alive)TCP 数据包一个预定义的时间间隔只是为了保持连接打开。
  • 我尝试了您的建议,但得到了相同的响应。但是我尝试将服务器中的请求提升到本地主机,在这种情况下它工作正常。我认为您关于代码的建议部分正确。
  • 问题已解决并找到解决方案,请参考my answer
【解决方案2】:

经过这么多的研究和调试,终于找到了问题所在。问题出在 apache webserver 中的代理,因为我们正在重定向连接,有近三个来自公共 IP 的重定向连接从 本地网络服务器连接再次被重定向到 api 端点。从 api 连接再次重定向到 另一个 api。所以现在由于 api 需要很长时间来响应 apache webserver 认为连接已丢失并返回代理错误。因此,如果我直接点击其余 api 端点,它就可以正常工作。感谢@randomiranswer 帮助我解决了问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-12
    • 2011-01-12
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    • 2018-08-01
    • 1970-01-01
    相关资源
    最近更新 更多