在Python开发的Web服务场景中,Brotli和zstd是两种高效的响应压缩算法,相比传统的gzip能带来更好的压缩比和传输性能,但要正确开启这两种压缩,需要满足一系列客户端和服务端的对应条件。

Brotli压缩的开启条件
客户端侧条件
客户端发起请求时,必须在Accept-Encoding请求头中包含br标识,告知服务端自身支持Brotli压缩格式的响应。如果请求头中没有该标识,服务端即使配置了Brotli压缩也不会生效。
服务端侧条件
首先需要在Python环境中安装Brotli依赖,使用pip执行安装命令:
pip install brotli
其次,服务端需要根据客户端的Accept-Encoding头动态判断,仅当检测到包含br时才对响应内容进行Brotli压缩。同时需要注意,Brotli压缩对文本内容(如HTML、CSS、JS、JSON)效果较好,对已经压缩过的二进制内容(如图片、视频)不建议开启,避免浪费CPU资源。
以Flask框架为例,开启Brotli压缩的示例代码如下:
from flask import Flask, request, Response
import brotli
app = Flask(__name__)
@app.after_request
def add_brotli_encoding(response):
# 检查客户端是否支持Brotli
if 'br' not in request.headers.get('Accept-Encoding', ''):
return response
# 仅对文本类响应进行压缩
if 'text' not in response.content_type and 'json' not in response.content_type:
return response
# 压缩响应内容
data = response.get_data()
compressed_data = brotli.compress(data)
response.set_data(compressed_data)
response.headers['Content-Encoding'] = 'br'
response.headers['Vary'] = 'Accept-Encoding'
return response
if __name__ == '__main__':
app.run(debug=True)
zstd压缩的开启条件
客户端侧条件
客户端需要在Accept-Encoding请求头中包含zstd标识,部分新版本的浏览器和HTTP客户端已经默认支持该标识,旧版本客户端可能需要手动配置请求头。
服务端侧条件
首先安装zstd的Python依赖:
pip install zstandard
服务端同样需要先校验客户端的Accept-Encoding头,确认支持zstd后再执行压缩。zstd压缩支持设置不同的压缩级别,级别越高压缩比越好但CPU消耗越大,默认级别为3,可根据服务性能灵活调整。
以FastAPI框架为例,开启zstd压缩的示例代码如下:
from fastapi import FastAPI, Request, Response
import zstandard as zstd
app = FastAPI()
# 初始化zstd压缩器,默认压缩级别为3
compressor = zstd.ZstdCompressor()
@app.middleware("http")
async def add_zstd_encoding(request: Request, call_next):
response: Response = await call_next(request)
# 检查客户端是否支持zstd
if 'zstd' not in request.headers.get('Accept-Encoding', ''):
return response
# 仅对文本内容压缩
if 'text' not in response.headers.get('content-type', '') and 'json' not in response.headers.get('content-type', ''):
return response
# 读取响应内容并压缩
body = b""
async for chunk in response.body_iterator:
body += chunk
compressed_body = compressor.compress(body)
response.body = compressed_body
response.headers['Content-Encoding'] = 'zstd'
response.headers['Vary'] = 'Accept-Encoding'
response.headers['Content-Length'] = str(len(compressed_body))
return response
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
通用注意事项
- 两种压缩算法都需要在响应头中正确设置
Content-Encoding字段,值为对应的br或zstd,否则客户端无法正确解码响应内容。 - 建议同时设置
Vary: Accept-Encoding响应头,避免缓存服务缓存错误编码的响应内容,导致后续请求返回无法解码的结果。 - 可以设置压缩阈值,比如响应内容长度小于1024字节时不开启压缩,因为小内容压缩后体积变化不大,反而增加CPU开销。
- 如果同时支持多种压缩算法,服务端应优先选择客户端支持且压缩比更好的算法,通常优先级为zstd > Brotli > gzip。
当满足上述客户端和服务端的对应条件后,Python Web服务就可以正确开启Brotli或zstd响应压缩,有效提升接口的传输效率。