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

HTTP大文件传输远慢于SCP的原因及性能优化咨询

问题解答

1. 这种传输性能差异是否正常?

是正常的,但差距可以通过针对性优化大幅缩小。

核心原因:

  • scp基于SSH协议,是面向字节流的极简传输,协议封装开销极低,且SSH经过多年底层优化,传输效率接近网络带宽上限。
  • 你当前的HTTP实现使用multipart/form-data格式(requests的files参数默认采用该格式),会给文件内容添加大量分隔符、头部元数据,服务器端需要额外解析这些封装内容,带来显著的CPU和IO开销;同时Python的requests、FastAPI默认的大文件处理逻辑未做针对性优化,进一步放大了性能差距。

2. 优化方法:让HTTP传输接近scp性能

客户端优化

(1)抛弃multipart格式,直接传输原始字节

避免files参数带来的封装开销,直接发送文件原始字节:

# 修改upload_image函数
def upload_image(image_path, url, verify_ssl, session):
    filename = os.path.basename(image_path)
    # 构造带文件名参数的URL
    upload_url = f"{url}?filename={filename}"
    with open(image_path, 'rb') as img:
        # 发送原始字节,设置对应Content-Type
        response = session.post(upload_url, data=img, verify=verify_ssl, headers={"Content-Type": "application/octet-stream"})
    try:
        response.raise_for_status()
    except requests.exceptions.HTTPError as e:
        print(f"HTTP error: {e}")
        return response.json()
    return response.json()

# 在main函数中初始化Session
def main():
    # ... 其他原有代码 ...
    session = requests.Session()
    # 配置连接池,复用连接减少TCP握手开销
    from requests.adapters import HTTPAdapter
    session.mount("https://", HTTPAdapter(pool_connections=10, pool_maxsize=10))
    session.mount("http://", HTTPAdapter(pool_connections=10, pool_maxsize=10))
    
    for image_path in filenames:
        # ... 其他原有代码 ...
        # 改用session发送请求
        response = upload_image(image_path, url, verify_ssl, session)

服务器端优化

(1)接收原始请求体,跳过multipart解析

修改FastAPI接口,直接读取请求体字节,避免解析multipart的额外开销:

from fastapi import Request
import aiofiles  # 需要先安装:pip install aiofiles

# 替换原有的upload-image接口
@app.post("/upload-image/")
async def upload_image_raw(request: Request, filename: str):
    file_location = f"uploaded_images/{filename}"
    Path("uploaded_images").mkdir(parents=True, exist_ok=True)
    # 异步分块写入文件,避免大文件占用过多内存
    async with aiofiles.open(file_location, "wb") as buffer:
        async for chunk in request.stream():
            await buffer.write(chunk)
    return {"info": "file uploaded successfully", "filename": filename}

(2)优化Uvicorn运行参数

利用多核CPU、更快的事件循环和解析器:

# 修改start_uvicorn函数中的uvicorn.run参数
uvicorn.run(
    f"{module_name}:app",
    host=args.host,
    port=args.port,
    log_level="info",  # 关闭debug日志,减少IO开销
    ssl_keyfile=keyfile,
    ssl_certfile=certfile,
    workers=4,  # 根据CPU核心数设置,例如核心数*2
    loop="uvloop",  # 需要安装uvloop:pip install uvloop
    http="httptools",  # 需要安装httptools:pip install httptools
    buffer_size=8*1024*1024  # 增大缓冲区到8MB,适配大文件传输
)

额外优化建议

  • 优先测试HTTP传输:先关闭HTTPS,排除SSL加密/握手的额外开销,验证优化效果后再考虑启用TLS1.3等高效SSL配置。
  • 启用HTTP/2:Uvicorn支持HTTP/2,配合支持HTTP/2的客户端(如使用hyper库的requests),可实现连接多路复用,进一步提升传输效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:53:21