【问题标题】:Flask App Response Not Received Client SideFlask App 响应未收到客户端
【发布时间】:2020-08-13 00:57:08
【问题描述】:

我有一个烧瓶应用程序运行一些计算,我从 Jupyter 笔记本发出请求。客户端代码遵循基本格式:

outputs = []
for batch in request_batches:
    response = requests.post(flask_address, json=json.dumps(batch), timeout=3600)
    outputs.append(response)

这个想法是遍历一系列请求批处理(批处理对应用程序有意义)并收集响应。

通常情况下,对于每个批次,我都会在 Flask 应用端看到记录的请求,以及计算完成后对 Post 的确认。

00.000.000.000 - - [29/Apr/2020 02:21:46] "POST //docking HTTP/1.1" 200 -

一批完成后,循环继续并发送下一个请求。

我遇到的问题是有时 Flask 大小的计算时间比正常情况要长一些,这会导致笔记本中的请求循环挂起(请注意,比正常时间长几分钟,远低于设置超时时间)。在 Flask 大小上,计算成功完成并有一个 Post 确认。

在笔记本大小上,循环挂起,不再发出请求。这不是超时问题 - 没有超时错误。笔记本单元会一直挂起,直到我手动中断它。

当我中断时,我看到以下堆栈跟踪:

~/opt/anaconda3/envs/env/lib/python3.7/socket.py in readinto(self, b)
    587         while True:
    588             try:
--> 589                 return self._sock.recv_into(b)
    590             except timeout:
    591                 self._timeout_occurred = True

中断后,我可以确认导致循环挂起的响应没有添加到输出中。所以不知何故 Flask 应用程序正在发布响应,但客户端笔记本没有收到响应。同样 95% 的时间运行良好,但 5% 的请求需要更长的时间来处理会导致请求循环冻结。

有人知道如何调试吗?

【问题讨论】:

    标签: python flask python-requests jupyter-notebook


    【解决方案1】:

    这很可能是由于套接字断开连接。在此处查看问题: https://github.com/psf/requests/issues/3353

    您可以设置 TCP keepalive 计时器来解决这个问题。

    # Set TCP keep alive options to avoid HTTP requests hanging issue
    # Reference: https://stackoverflow.com/a/14855726/2360527
    import platform
    import socket
    import urllib3.connection
    
    platform_name = platform.system()
    orig_connect = urllib3.connection.HTTPConnection.connect
    def patch_connect(self):
        orig_connect(self)
        if platform_name == "Linux" or platform_name == "Windows":
            self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
            self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 1),
            self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 3),
            self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5),
        elif platform_name == "Darwin":
            TCP_KEEPALIVE = 0x10
            self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
            self.sock.setsockopt(socket.IPPROTO_TCP, TCP_KEEPALIVE, 3)
    urllib3.connection.HTTPConnection.connect = patch_connect
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多