You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何计算FastAPI端点收发数据时的文件往返网络传输耗时

FastAPI端点文件传输分段耗时统计方案

核心统计逻辑

要排除接口总响应时长里的服务端业务处理耗时,仅统计传输环节耗时,逻辑如下:

  • 文件上传耗时:服务端完全接收完上传文件最后一个字节的时间 - 服务端开始接收文件第一个字节的时间
  • 文件回传耗时:主机接收完下载文件最后一个字节的时间 - 服务端开始发送文件第一个字节的时间

代码实现

1. 上传耗时统计(服务端侧可直接完成,无需客户端配合)

通过依赖注入的方式仅对需要统计的接口生效,避免全局中间件带来的性能损耗:

from fastapi import FastAPI, Request, UploadFile, File, Depends
import time

app = FastAPI()

async def count_upload_duration(request: Request):
    # 记录开始读取请求体(文件内容)的时间
    start_recv = time.perf_counter()
    # 完整读取请求体
    await request.body()
    # 计算上传传输耗时,存入请求上下文
    request.state.upload_cost = time.perf_counter() - start_recv

@app.post("/upload", dependencies=[Depends(count_upload_duration)])
async def upload_endpoint(request: Request, file: UploadFile = File(...)):
    # 直接获取上传传输耗时,单位为秒
    upload_cost = request.state.upload_cost
    # 此处添加你自己的文件处理逻辑
    return {"upload_transfer_duration_seconds": round(upload_cost, 4)}

2. 回传耗时统计

回传耗时属于端到端指标,需要客户端配合完成,以下给出两种常用统计方案:

方案一:服务端统计发送全流程耗时

仅统计服务端从开始发送到把所有字节推送到网卡的耗时,适合不需要精确端到端耗时的场景:

from fastapi.responses import StreamingResponse

@app.get("/download")
async def download_endpoint():
    # 模拟待返回的文件内容
    test_file = b"test_content" * 10000
    start_send = time.perf_counter()
    
    def file_generator():
        yield test_file
    
    resp = StreamingResponse(
        file_generator(),
        media_type="application/octet-stream"
    )
    
    # 发送完成后的回调,统计服务端侧发送耗时
    @resp.background
    def after_send_callback():
        send_cost = time.perf_counter() - start_send
        # 可自行存储该指标到日志/数据库
        print(f"服务端发送耗时: {round(send_cost,4)}s")
    
    return resp

方案二:端到端精确统计

要求客户端与服务端时钟同步(NTP同步下误差一般<10ms),通过响应头传递时间戳计算:
服务端代码修改:

@app.get("/download")
async def download_endpoint():
    test_file = b"test_content" * 10000
    # 取Unix时间戳,跨机器可对比
    start_send_ts = time.time()
    def file_generator():
        yield test_file
    return StreamingResponse(
        file_generator(),
        media_type="application/octet-stream",
        # 把发送开始时间戳放到自定义响应头
        headers={"X-Send-Start-Ts": str(start_send_ts)}
    )

客户端(Python示例)计算逻辑:

import requests
import time

resp = requests.get("http://你的服务端地址/download", stream=True)
# 读取服务端发送开始时间戳
send_start = float(resp.headers["X-Send-Start-Ts"])
# 读取完整响应内容
file_content = b""
for chunk in resp.iter_content(chunk_size=1024):
    file_content += chunk
# 计算端到端回传耗时
transfer_cost = time.time() - send_start
print(f"端到端回传耗时: {round(transfer_cost,4)}s")

内容的提问来源于stack exchange,提问作者alz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 04:24:03