FastAPI 服务器在发送 Twilio 消息时变得无响应

问题描述 投票:0回答:1

我有一个 FastAPI 应用程序 (obvs),它有一个端点,它使用 Twilio 的客户端发送消息同步。这没有奏效。我制作了一个简单的 python 文件,它只构建客户端并创建消息,它工作正常,所以我不怀疑它是 twilio 本身。使用 twilio 客户端进行呼叫时,服务器挂起/冻结。它永远不会超时。如果我在此期间更改文件,重新加载器也会冻结(我假设服务器已变得无响应)。无论我是否为此路由使用同步或异步路径定义,都会发生这种情况。其他异步和同步路由似乎工作正常(我还没有抽出时间来测试它们)。

fastapi==0.104.1
twilio==8.2.0
uvicorn==0.23.2
starlette==0.27.0

我像这样在本地运行应用程序(我还直接从命令行调用 uvicorn):

if __name__ == '__main__':
    uvicorn.run('app:app', reload=True, port=5002)

我在单独的文件中有一个路由器,并在应用程序的构建器函数中调用 app.include_router() 。这是 twilio 客户端(我们有自己的 lil 包装器):

from twilio.rest import Client
...get env variables

class TwilioAPI
    def __init__(self, phone_number: str):
        self.client = Client(account_sid, auth_token)
        self.phone_number = phone_number

    def send_sms(self, body: str):
        # we enter the function, but this never returns/resolves
        message = self.client.messages.create(
            messaging_service_sid=messaging_service_sid,
            body=body,
            to=self.phone_number,
        )
        return message.sid

所讨论的路线如下所示:

@router.post("/endpoint")
def send_message_or_whatever(input: Input):
    ...get data from input, construct message
    ...we hit our database here and this works
    twilio_api_client = CreateAnInstanceOfOurTwilioClient()
    twilio_api_client.send_sms(message) <--- this is where it goes sideways
    return stuff

我在 twilio 自己的博客上找到的所有示例都做了类似的事情

@router.post('/endpoint')
async def do_something():
    client = twilio.rest.Client() # synchronous client
    client.messages.create(...create message params)

我尝试过的东西:

使用异步和同步路径定义。即使我们在同步功能中“等待”twilio,但这并不重要?我们在其他点等待数据库,这是一个没有问题的网络调用。现在我什至不关心它是否不是性能最佳的东西。客户端不会返回必须等待的未来。

使用异步时,我尝试使用

await asyncio.get_event_loop().run_in_executor(...)
无济于事,什么也没有发生

我尝试使用fastapi的后台任务。它仍然卡在

client.messages.create
(我猜这是
asyncio.to_thread
run_in_executor
的包装)

我到底做错了什么?

PS:我知道 twilio 客户端的 AsyncHTTPClient,但我主要感兴趣的是了解为什么这不起作用

python twilio python-asyncio fastapi uvicorn
1个回答
0
投票

同步调用阻塞了事件循环。这就是为什么你会看到这种行为。在线程或线程池执行器中运行它会出现问题,因为 Twilio 默认使用请求会话,这不是线程安全的。

Twilio 还指出他们的客户端不应被视为线程安全的。

线程安全问题会导致死锁等问题。您可以通过在使用客户端的线程中创建客户端来避免此问题,而不是跨线程重用同一客户端。 但是你最好的选择就是使用异步客户端。

© www.soinside.com 2019 - 2024. All rights reserved.