使用aiohttp服务器并等待Future仅在超时后解析

时间:2019-06-19 13:59:59

标签: python aiohttp

上下文是,我正在为Mosquitto服务器编写Sidecar健康检查。作为对ping健康检查的响应,检查者可以发布一条消息并确认收到消息。

以下代码的问题是,它返回OK(成功发布/接收),但仅在asyncio.wait_for中的5秒超时到期之后才返回。尽管on_message被立即调用并设置了全球未来shared_result的结果。

Python 3.7.1 paho-mqtt:1.4.0 aiohttp:3.5.4 异步:3.4.3

import sys
import paho.mqtt.client as mqtt
import asyncio
from aiohttp import web
import concurrent

CHECK_TOPIC = "/healthcheck"
shared_result = None

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe(CHECK_TOPIC)

def on_message(client, userdata, msg):
    global shared_result
    print("on_message: " + msg.topic+" "+str(msg.payload))
    if msg.topic == CHECK_TOPIC and shared_result != None:
        shared_result.set_result("OK")
        shared_result = None

def check(fut):
    global shared_result
    shared_result = fut
    print("Publishing check topic")
    client.publish(CHECK_TOPIC, payload="CHECK", qos=0, retain=False)

client = mqtt.Client(client_id="checker", clean_session=True, userdata=None, protocol=mqtt.MQTTv311, transport="tcp")
client.on_connect = on_connect
client.on_message = on_message

client.connect("localhost", 1883, 60)

# Starts processing on a background thread
client.loop_start()

PORT = int(sys.argv[1])

async def handle(request):
    fut = asyncio.Future()
    check(fut)
    try:
      # TODO: Figure out why we don't get fut result immediately. Instead, we get it only after timeout.
      chk = await asyncio.wait_for(fut, timeout=5)
      return web.Response(text=chk, status = 200)
    except concurrent.futures._base.TimeoutError as e:
      return web.Response(text="NOK", status = 408)
    except Exception as ex:
      template = "An exception of type {0} occurred. Arguments:\n{1!r}"
      message = template.format(type(ex).__name__, ex.args)
      print(message)
      return web.Response(text="NOK", status = 500)

app = web.Application()
app.add_routes([web.get('/', handle),
                web.get('/{name}', handle)])
web.run_app(app, port = PORT)

任何帮助将不胜感激。

0 个答案:

没有答案