fastapi 如何控制并发——其二

业务背景

书接上文 gunicorn+fastapi 如何控制并发——其一 ,后续我又接到了模型服务化的需求,简单搭个demo服务支持业务验证和对比实验,后续我觉得使用 Nginx+gunicorn+FastAPI 这种办法实在太重了,有没有更简单的办法,可以暂时支撑一段时间?

其实我们这里使用一个全局变量加线程锁就可以解决这个问题,之前使用 gunicorn 是因为想是用框架的一些能力,只可惜实现并发限流及其困难。那么有没有什么比较简单的框架呢?后续调研到可以使用 uvicorn ,这是一种 ASGI 服务器框架,主要用于处理异步请求。因为``FastAPI使用的是ASGI标准,而之前使用的gunicorn` 是用于处理同步请求的,使用的是 WSGI 标准,例如 Flask,Django等,两种协议之间差异参考这里

我们甚至可以直接在python代码中启动服务,直接使用 python app.py 就可以启动HTTP服务:

import uvicorn
from fastapi import FastAPI

app = FastAPI()


@app.get("/hello")
def predict():
    return "world"


if __name__ == "__main__":
    uvicorn.run(
        app="main:app",
        host="0.0.0.0",
        port=8000,
        log_level="debug",
    )

那如何实现控制并发呢,因为 uvicorn 是基于 ASGI 协议的服务框架,因此在接收请求时,不必等待worker 空闲,默认worker能够异步处理多个请求。因此如果我们只是支持:每个worker支持1个并发,那么可以通过线程锁的方式来判断当前work是否繁忙,例如:

import uvicorn
from threading import Lock
from fastapi import FastAPI, HTTPException

app = FastAPI()

lock = Lock()
import time


@app.get("/hello")
def predict():
    acquired = lock.acquire(blocking=False)
    if acquired:
        try:
            time.sleep(1)
        finally:
            lock.release()
        return "world"
    else:
         raise HTTPException(
            status_code=503,
            detail="service busy",
        )


if __name__ == "__main__":
    uvicorn.run(
        app="main:app",
        host="0.0.0.0",
        port=8000,
        log_level="debug",
        workers=10,
    )

我们通过非阻塞的方式获取线程锁,然后判断是否能够拿到锁,如果不能则立刻返回503错误。而且如果模型可以支持异步流式,我们甚至可以控制worker的并发度。相比之前 Nginx+gunicorn+FastAPI 的方案,这种方法简直不要简单太多。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值