簡體   English   中英

FastAPI如何將ZMQ添加到事件循環

[英]FastAPI how to add ZMQ to eventloop

我很驚訝這並沒有真正被詳細詢問,但由於某種原因,我無法在任何地方找到這個問題或解決方案。 似乎很多人都遇到了一個問題,你有一個 fastAPI 應用程序,它還需要與其他一些微服務通信(比 http 消息更有效)。 我已經閱讀了所有關於集成到 asyncio 的 zmq 文檔,但是到目前為止,我還沒有找到任何關於如何使用 fastapi(甚至是 starlette)將 zmq 添加到事件循環中的信息。 這是 zmq 網站上的代碼示例:

import asyncio
import zmq
from zmq.asyncio import Context

ctx = Context.instance()

async def recv():
    s = ctx.socket(zmq.SUB)
    s.connect('tcp://127.0.0.1:5555')
    s.subscribe(b'')
    while True:
        msg = await s.recv_multipart()
        print('received', msg)
    s.close() 

這向我們展示了一個異步 function,這很棒,但再次需要在事件循環中與 fastAPI 協程一起運行。 這應該怎么做? 除了后台任務之外,fastAPI 文檔並沒有真正為我們提供任何接口來運行單獨的協程。 我不確定后台任務中是否發生了任何其他魔法,但對於需要與另一個微服務通信的東西,我希望它具有類似於 fastAPI 協程的調度。 此外,您無法在啟動時啟動后台任務,因此您必須進行一些欺騙性的調用才能使其運行(這很hacky ..但在技術上有效)。 此外,如果我們可以只注冊一個處理程序,那就更好了

@app.set("zmq_recv)
async def recv():
    s = ctx.socket(zmq.SUB)
    s.connect('tcp://127.0.0.1:5555')
    s.subscribe(b'')....

這將基於某處的配置,允許 zmq 上下文中的所有消息自動 go 到此 function。 這可能允許我們在 fastAPI 協程中運行 zmq,只需綁定另一個端口,並確保來自該端口的所有流量都流向這個特殊的 app.set 方法。 像這樣的東西我會很好......

ctx = Context.instance()

@app.on_event("startup")
async def startup_event():
    s = ctx.socket(zmq.PULL)
    s.bind('tcp://127.0.0.1:5555').setHandler("zmq_recv") # this setHandler is something magic that tells fastAPI to have all traffic on port 5555 to go to this handler function

@app.on_special_handler("zmq_recv")
async def zmq_recv(socket):
    msg = await socket.recv_multipart()
    print('received', msg)
    

理想情況下,這是我想要的,使用 fastAPI 協程......但是讓 zmq sockets 調用對特定 function 的響應。 是否可以創建協程示例或這種模板化示例? 如果不是,人們如何聲稱您可以有效地將 zmq 與 fastapi 一起使用? (我想后台任務可以解決問題..但它似乎真的很虛偽)

我實際上正在做類似的事情,特別是通過非 http 處理程序來監聽來自消息隊列的事件。 我當前的解決方案是連接到事件循環並在那里添加監聽器。 它可能看起來像這樣:(取自 fastapi -> issue中的這個問題)

loop = asyncio.get_event_loop()

loop.create_task(serve(app, config))  # run fastapi
loop.create_task(your_tcp_app()) # run your app
loop.run_forever()  # start event loop

您也可以在初始化后調用應用程序正在使用的事件循環,這與您最初所做的更相似:

@app.on_event("startup")
async def startup_event():
    loop = asyncio.get_event_loop() # should return the loop fastapi is already using
    loop.create_task(your_tcp_app()) # run your app

我正在考慮這個解決方案,因為我害怕 python 中的線程管理,因為這將存在於生產服務中,我可能最終將兩個進程完全分開以使事情變得更簡單......我想要知道這是否對您有用,或者其他人是否對這種實現有任何想法:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM