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
相关产品推荐
相关产品推荐

