FastAPI使用async?乱用async导致灾难,不如直接不用

本文通过一个实例展示了在FastAPI中误用async关键字导致的请求阻塞问题。当async函数内部执行的是同步代码时,会导致并发执行失效。解决方法是删除async关键字,改为普通函数。理解并正确使用异步编程对于优化服务性能至关重要。
摘要由CSDN通过智能技术生成

警告:乱用async导致灾难

背景

研发过程中,测试同事反馈,调用XX接口的时候其他的接口全部没法调用了,都被阻塞住了。

我当时认为,机器太挫了,有其他任务在机器上运行,请求无法处理。但,很快我就被打脸。

这里用一个DEMO来展示,只包含了三个文件

第一个文件  fastApiServer,这个文件里面定义了两个API,并启动了服务器

import xmlrpc.client
import uvicorn
from datetime import datetime
from fastapi import FastAPI

app = FastAPI()


@app.get("/root1")
async def root1():
    print("1111", datetime.now())
    # 调用RPC
    url = 'http://{}:{}'.format("127.0.0.1", 1081)
    client = xmlrpc.client.ServerProxy(url)
    res = client.test1()
    if res is not None:
        print(res)
    # 调用RPC结束
    print("2222", datetime.now())
    return {"message": "Hello World"}


@app.get("/root2")
async def root2():
    print("3333", datetime.now())
    # 调用RPC
    url = 'http://{}:{}'.format("127.0.0.1", 1081)
    client = xmlrpc.client.ServerProxy(url)
    res = client.test2()
    if res is not None:
        print(res)
    # 调用RPC结束
    print("4444", datetime.now())
    return {"message": "Hello World"}


uvicorn.run(app=app, host="0.0.0.0", port=1080, timeout_keep_alive=1200)

第二个文件rpcServer.py

import time
from socketserver import ThreadingMixIn
from xmlrpc.server import SimpleXMLRPCServer


class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
    name = "xml-server"


def test1():
    print("test1()")
    time.sleep(10)
    status = "1"
    return status


def test2():
    print("test2()")
    status = "2"
    return status


server = ThreadXMLRPCServer(('0.0.0.0', 1081))
server.register_function(test1, "test1")
server.register_function(test2, "test2")
server.serve_forever()

第三个文件 test.py 测试文件,先后发送两个请求

import time
from threading import Thread

import requests


def k1():
    requests.get(url="http://127.0.0.1:1080/root1")


def k2():
    requests.get(url="http://127.0.0.1:1080/root2")


Thread(target=k1).start()
time.sleep(1)
Thread(target=k2).start()

启动服务


跑测试

 

我震惊发现,两个先后间隔1秒到达的请求,竟然需要等待第一个请求结束之后,才会去处理第二个请求

问题原因

如果你定义了async函数,函数体却是同步的调用,将导致函数执行过程变成串行。

解决方案

方法一 直接删除async

import xmlrpc.client
import uvicorn
from datetime import datetime
from fastapi import FastAPI

app = FastAPI()


@app.get("/root1")
def root1():
    print("1111", datetime.now())
    # 调用RPC
    url = 'http://{}:{}'.format("127.0.0.1", 1081)
    client = xmlrpc.client.ServerProxy(url)
    res = client.test1()
    if res is not None:
        print(res)
    # 调用RPC结束
    print("2222", datetime.now())
    return {"message": "Hello World"}


@app.get("/root2")
def root2():
    print("3333", datetime.now())
    # 调用RPC
    url = 'http://{}:{}'.format("127.0.0.1", 1081)
    client = xmlrpc.client.ServerProxy(url)
    res = client.test2()
    if res is not None:
        print(res)
    # 调用RPC结束
    print("4444", datetime.now())
    return {"message": "Hello World"}

uvicorn.run(app=app, host="0.0.0.0", port=1080, timeout_keep_alive=1200)

修改后,再次运行测试脚本

结果和预期一致。

结论

在不了解所调用函数是否支持await的情况下,不使用async,使用普通函数即可

参考链接

https://blog.csdn.net/qq_29518275/article/details/109360617

https://fastapi.tiangolo.com/async/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

康雨城

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值