为了账号安全,请及时绑定邮箱和手机立即绑定

基于FastAPI构建能够处理在线和离线请求的生产级Python应用

要介绍一下

由于其异步能力、自动创建的文档和高性能,FastAPI赢得了巨大的人气。在这篇博客文章中,我们将介绍如何构建一个基于 FastAPI 的 Python 应用程序,该应用程序可以处理在线和离线请求(例如同步API请求和使用Amazon SQS队列的后台任务)。我们将介绍生产就绪的最佳实践、处理线程管理和实现定时任务。

1.: 应用设计概览

一个可投入生产的健壮 FastAPI 应用架构通常包含:

  • API 层: 负责处理同步的 API 请求。
  • 后台工作者层: 处理长时间运行或异步的任务,使用队列(如 SQS)。
  • 数据库和缓存层: 存储响应所需的数据。
  • 任务调度器: 用于安排定期任务。
  • 监控与健康检查: 用于确保系统的可观察性。

这里有一个高层次的设计图,便于大家理解:

API Gateway → FastAPI 应用程序 → (同步响应消息)
→ SQS 消息队列 → 后台任务处理程序 → 数据库和缓存

2. 设置 FastAPI 应用程序:

我们先来构建一个 FastAPI 项目结构:

这是一个简单的应用目录结构示例。
app/  
├── main.py  
├── API/  
│   └── 接口.py  
├── 任务执行器/  
│   └── 背景任务.py  
├── 数据模型/  
│   └── 模型.py  
├── 配置.py  
└── 工具/  
    └── 调度器.py

main.py (主程序)

    from fastapi import FastAPI, BackgroundTasks  
    from app.api.endpoints import router as api_router  
    import boto3  
    import os  

    app = FastAPI()  

    # 初始化SQS客户端实例  
    sqs_client = boto3.client(  
        "sqs",  
        region_name=os.getenv("AWS_REGION"),  
        aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),  
        aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY")  
    )  

    @app.get("/health")  
    def health_check():  
        return {"status": "ok"}  

    # 加入API端点定义  
    app.include_router(api_router)
3. 处理在线请求(同步API)

这里有一个直接处理用户请求的 API 端点的例子。

    # endpoints.py
    from fastapi import APIRouter, HTTPException
    from app.workers.background_tasks import enqueue_task

    router = APIRouter()

    @router.post("/process-online")
    def process_online(data: dict):
        # 执行在线同步处理
        result = {"message": "在线处理成功完成", "input": data}
        return result

    @router.post("/process-offline")
    def process_offline(data: dict):
        # 将任务加入队列等待离线处理
        enqueue_task(data)
        return {"message": "任务已加入队列等待离线处理"}
4. 使用SQS处理非实时请求(后台任务)

一个后台工作者监听着SQS队列中的消息并进行处理。

workers/背景任务.py

    import boto3  
    import time  
    import os  

    sqs_queue_url = os.getenv("SQS_QUEUE_URL")  

    # 向SQS队列中入队任务  
    def enqueue_task(data):  
        sqs_client.send_message(  
            QueueUrl=sqs_queue_url,  
            MessageBody=str(data)  
        )  
        print("打印 '消息已发送到SQS'")  

    # 轮询SQS队列的工作函数  
    def process_sqs_messages():  
        while True:  
            messages = sqs_client.receive_message(  
                QueueUrl=sqs_queue_url,  
                MaxNumberOfMessages=10,  
                WaitTimeSeconds=10  
            )  

            if 'Messages' in messages:  
                for message in messages['Messages']:  
                    print("打印 '正在处理消息:', message['Body']")  
                    # 在这里执行耗时处理  
                    time.sleep(2)  # 模拟处理时间  

                    # 处理完成后删除消息  
                    sqs_client.delete_message(  
                        QueueUrl=sqs_queue_url,  
                        ReceiptHandle=message['ReceiptHandle']  
                    )

运行后台任务:

在命令行中输入以下命令来运行处理SQS消息的脚本:

python -m app.workers.background_tasks.process_sqs_messages

注释: 这是一个用于处理SQS消息的Python命令。python -m 语法用于运行Python的模块或包。

5. 管理在 FastAPI 中的线程管理

默认,FastAPI 使用异步协程处理并发情况。不过,特定任务可能需要线程。

例子:并行执行任务:

如果你想实现并行处理,可以试试使用 concurrent.futures.ThreadPoolExecutor 这个工具。它可以帮助你在程序中实现并行执行,从而提高效率。

    import concurrent.futures  
    from fastapi import BackgroundTasks  

    executor = concurrent.futures.ThreadPoolExecutor(max_workers=5)  

    @app.get("/heavy-task")  
    def run_heavy_task():  
        future = executor.submit(expensive_function)  
        return {"message": "任务正在执行"}
6. FastAPI中的生命周期

FastAPI 提供了一个生命周期处理器函数,在应用启动和关闭时执行代码。

    from fastapi import FastAPI  
    from contextlib import asynccontextmanager  

    @asynccontextmanager  
    async def lifespan(app: FastAPI):  
        print("开始启动...")  
        yield  
        print("开始关闭...")  

    app = FastAPI(lifespan=lifespan)

用寿命来,

或者更口语化地表达为:用寿命来干啥:

  • 初始化数据库连接过程,
  • 启动后台任务。
7. FastAPI中的计划任务

虽然 FastAPI 本身没有内置的功能支持定时任务,你可以使用例如 APSchedulerCelery 这样的第三方库来执行周期性任务。

APS 调度器例子:
    from apscheduler.schedulers.background import BackgroundScheduler  

    scheduler = BackgroundScheduler()  

    # 定义周期性任务  
    @scheduler.scheduled_job("间隔", seconds=60)  
    def 周期性任务():  
        print("执行计划任务")  

    scheduler.start()  

    @app.on_event("关闭")  
    def 关闭事件():  
        scheduler.shutdown()
示例
  • 在线API请求: 用户提交的数据会被立即处理并返回。
  • 离线处理: 大型文件或耗时较长的请求会被加入SQS队列并在稍后处理。
  • 定时任务: 每分钟,都会将处理的任务报告发送到监控系统。
8. 生产准备考虑
  • 环境变量: 使用 .env 文件和 AWS Secrets Manager 来管理敏感配置信息。
  • 安全: 使用 OAuth2 或 JWT 进行 API 认证。
  • 可扩展性: 在负载均衡器(如 AWS ALB)后面部署 FastAPI。
  • 监控: 与 Prometheus/Grafana 集成以监控性能指标。
  • 重试和死信队列: 配置 SQS 以处理重试逻辑,并将未处理的任务移至死信队列(DLQ)。
结论:

FastAPI 的轻量级和异步功能使其成为构建既处理在线请求又处理离线请求的 API 的绝佳选择。通过利用 SQS 等工具进行后台任务处理以及 APScheduler 进行定时任务,您可以创建一个健壮且可投入生产的系统。通过周全的设计、适当的线程管理和有效的监控,您的 FastAPI 应用程序将在实际应用中具备高扩展性和高效率。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消