首页 > 其他分享 >fastapi 接口阻塞问题处理

fastapi 接口阻塞问题处理

时间:2023-08-15 22:24:16浏览次数:46  
标签:test1 test2 -- fastapi work 阻塞 接口 耗时 time

原文地址:https://blog.csdn.net/qq_42006301/article/details/124873383

背景

在使用fastapi框架开发时,遇到一个坑,在请求某个耗时的接口时,再请求其他接口,发现请求都被阻塞卡住了,经过排查问题,发现是async使用不当导致的

问题复现

这里写了一个小demo文件,里面有耗时函数work 和 两个接口 /test1、 /test2

def work(s):
    print("work start work")
    time.sleep(s)
    print("work end work")


@api.get("/test1")
async def test1():
    print("func: test1")
    return "test1"


@api.get("/test2")
async def test2():
    a = int(time.time())
    print(f"start: {a}")
    work(8)
    b = int(time.time())
    print(f"start: {b-a}")
    return f"test2耗时:{b-a}"

使用如下测试脚本请求接口测试

import time
import requests
from threading import Thread

def task1():
    a = int(time.time())
    requests.get(url="http://127.0.0.1:8000/test/test1")
    b = int(time.time())
    print(f"test1耗时{b - a}")


def task2():
    a = int(time.time())
    requests.get(url="http://127.0.0.1:8000/test/test2")
    b = int(time.time())
    print(f"test2耗时{b - a}")


Thread(target=task1).start()
Thread(target=task2).start()

运行测试脚本发现,/test1被阻塞了,等/test2处理完之后,/test1 才返回结果
执行顺序如下

test2--start: 1652973708
work start work
work end work
test2--end: 1652973716
test1--执行
INFO:     127.0.0.1:63965 - "GET /test/test2 HTTP/1.1" 200 OK
INFO:     127.0.0.1:63966 - "GET /test/test1 HTTP/1.1" 200 OK

测试脚本

test1耗时8
test2耗时8

Process finished with exit code 0

可以看到,/test1在/test2执行完之后才执行,/test1请求同样耗时8秒
解决方法1
直接删除掉 /test2 的 async(fastapi会按照多线程的方式进行处理)
改为如下:

@api.get("/test2")
def test2():
    a = int(time.time())
    print(f"test2--start: {a}")
    work(8)
    b = int(time.time())
    print(f"test2--end: {b}")
    return f"test2耗时:{b-a}"

此时运行测试脚本,执行顺序如下

test1--执行
test2--start: 1652973918
work start work
INFO:     127.0.0.1:64024 - "GET /test/test1 HTTP/1.1" 200 OK
work end work
test2--end: 1652973926
INFO:     127.0.0.1:64023 - "GET /test/test2 HTTP/1.1" 200 OK

耗时

test1耗时0
test2耗时8

Process finished with exit code 0

解决方法2

利用asyncio获取当前的event loop。
然后将耗时函数work放到一个event loop中去运行

@api.get("/test2")
async def test2():
    a = int(time.time())
    print(f"test2--start: {a}")
    loop = asyncio.get_event_loop()
    await loop.run_in_executor(None, work, 8)
    b = int(time.time())
    print(f"test2--end: {b}")
    return f"test2耗时:{b-a}"

执行顺序如下

test2--start: 1652974163
work start work
test1--执行
INFO:     127.0.0.1:64094 - "GET /test/test1 HTTP/1.1" 200 OK
work end work
test2--end: 1652974171
INFO:     127.0.0.1:64093 - "GET /test/test2 HTTP/1.1" 200 OK

耗时

test1耗时0
test2耗时8

Process finished with exit code 0

总结

如果定义了async函数,函数体却是同步的调用,将导致函数执行过程变成串行,所以在 async函数里如果有io等阻塞的地方一定要使用 await 将程序挂起。

标签:test1,test2,--,fastapi,work,阻塞,接口,耗时,time
From: https://www.cnblogs.com/bitterteaer/p/17632596.html

相关文章

  • 新增@ComponentScan,访问接口404?
    1.起因:自定义一个接口日志注解。打算为所有的接口打印日志和耗时等信息。将定义的@IfLog注解加到HiController的/hi接口因为Application仅扫描和他同一个包下所有类,所以在启动类上增加了@ComponentScan({"com.wxy.log.common"})用于扫描新增的日志切面。访问接......
  • Python Fire:自动生成命令行接口
    首先创建一个 student_file.pypipinstallfire使用 Fire 转换成命令行程序 1.默认方式importfiredefimport_file(fp):print("函数1打印结果:{}".format(fp))defexport_file(fp):print("函数2打印结果:{}".format(fp))if__name__=="__m......
  • 订单支付_微信支付介绍_微信支付相关接口介绍
        ......
  • fastapi常用的启动方式
      demogunicornmain:app-b0.0.0.0:11223-w10-kuvicorn.workers.UvicornH11Worker--daemon#在线上先这样才能看到报错信息uvicornmain:app--reload--host0.0.0.0uvicornmain:app--reloadgunicorn-cgunicorn_info.pyinfo:appps-ef|grepgun......
  • ThingsKit物联网平台可视化工具之大屏公共接口配置
    概述在大屏设计器中,主要是提供一些标准接口和过滤器,以便在大屏设计器中,供各个大屏可以调用该公共接口;接口属于通用性接口,具体交互和以及参数配置都是在大屏设计页面中完成;不同的接口,参数配置不同。功能说明新增接口首先,进入公共接口管理页;单击“新增公共接口”按钮,在弹出的新......
  • SPOE交换机如何级联,SPOE接口和SPOE接口能直连吗?
    SPOE交换机在数字楼宇对讲中都需要使用到,最近有朋友问SPOE机交换机怎么级联?SPOE端口可以和SPOE端口连接吗?今天小柏就和大家讲解一下上次两个问题吧!SPOE交换机如何级联?SPOE交换就是强制性供电的,所以SPOE接口和SPOE接口不能直连,直连两个口都带电,会烧毁接口或交换机,SPOE的端口可以接不......
  • 接口测试的测试用例该怎么写呢
    接口测试是软件测试中非常重要的一部分,因为接口的稳定性和可靠性对于整个系统的质量和用户体验都有很大的影响。在接口测试中,编写有效的测试用例是非常关键的一步。本文将介绍如何编写接口测试的测试用例,包括测试用例的设计和编写方法,并提供一些具体的测试用例示例和代码实现。一、......
  • 用户下单_需求分析和设计_接口设计
         ......
  • 如何上传文件给接口
    1.首先要确保服务器的可以正常处理formdata;2.我们给接口的请求头应该是multipart/form-data 可以通过这样设置 3.如果这样设置也不行,比如目前的这个陆港项目就是这样设置也不行,那就不适用axios,使用fech;uploadFile(pdfData){letfileName=`${this.$store......
  • 小米发布全新CyberDog 2,体型接近真实小型犬,超80%开源率,100+接口开放
    小米发布全新CyberDog2,体型接近真实小型犬,超80%开源率,100+接口开放2023-08-1508:01:28 来源: 金融界分享到:8月14日,小米发布全新仿生四足机器人CyberDog2。该款产品在继承前代优势的基础上,进行了全面的技术升级:它配备了新一代小米自研高性能电机,提供了更为强大的动态响应......