在Flask接口开发过程中,当接口返回的数据体积较大时,会显著增加网络传输的耗时,同时也会消耗更多的服务器带宽资源。对接口响应进行Gzip压缩是一种高效的优化手段,它可以在不修改业务逻辑的前提下,大幅减少传输数据的大小,提升接口的响应速度。

Flask内置压缩中间件实现方式
Flask从较新的版本开始,内置了简单的响应压缩支持,我们可以通过配置直接开启基础的Gzip压缩功能,这种方式不需要引入额外的第三方库,适合对压缩要求不高的场景。
首先需要在创建Flask应用的时候进行相关配置,核心配置项是GZIP_COMPRESS_LEVEL,用来设置压缩的等级,等级范围是1到9,数值越高压缩率越高,但消耗的CPU资源也越多,通常设置为6是比较均衡的选择。
from flask import Flask
app = Flask(__name__)
# 开启Gzip压缩,设置压缩等级为6
app.config['GZIP_COMPRESS_LEVEL'] = 6
# 设置需要压缩的最小响应体大小,单位字节,默认是500
app.config['GZIP_MIN_SIZE'] = 500
# 开启内置的Gzip压缩支持
app.config['GZIP_ENABLED'] = True
@app.route('/api/data')
def get_data():
# 模拟返回大量数据
data = {'content': '测试数据' * 1000}
return data
if __name__ == '__main__':
app.run(debug=True)
自定义Gzip中间件实现方式
如果内置的压缩功能无法满足需求,比如需要自定义压缩的触发条件、或者需要兼容更老版本的Flask,我们可以自己实现Gzip中间件。自定义中间件的核心是拦截响应,判断是否需要压缩,然后对响应体进行Gzip压缩后重新设置响应头和响应体。
实现自定义中间件需要用到Python内置的gzip模块,同时需要判断请求头中的Accept-Encoding是否包含gzip,只有客户端支持Gzip压缩的时候才进行压缩操作。
import gzip
from flask import Flask, request, Response
from io import BytesIO
app = Flask(__name__)
class GzipMiddleware:
def __init__(self, app, compress_level=6, min_size=500):
self.app = app
self.compress_level = compress_level
self.min_size = min_size
def __call__(self, environ, start_response):
# 获取原始响应
response = self.app(environ, start_response)
# 检查客户端是否支持gzip
accept_encoding = environ.get('HTTP_ACCEPT_ENCODING', '')
if 'gzip' not in accept_encoding:
return response
# 获取响应体
response_body = b''.join(response)
# 如果响应体大小小于最小压缩阈值,不压缩
if len(response_body) < self.min_size:
return response
# 进行gzip压缩
buffer = BytesIO()
with gzip.GzipFile(fileobj=buffer, mode='wb', compresslevel=self.compress_level) as gz_file:
gz_file.write(response_body)
compressed_body = buffer.getvalue()
# 设置响应头
response.headers['Content-Encoding'] = 'gzip'
response.headers['Content-Length'] = len(compressed_body)
# 返回压缩后的响应
return [compressed_body]
# 注册自定义中间件
app.wsgi_app = GzipMiddleware(app.wsgi_app)
@app.route('/api/custom_data')
def get_custom_data():
data = {'info': '自定义中间件压缩数据' * 800}
return data
if __name__ == '__main__':
app.run(debug=True)
使用第三方库flask-compress实现
除了内置功能和自定义中间件,还可以使用成熟的第三方库flask-compress来实现Gzip压缩,这个库功能更完善,支持更多的压缩算法,配置也更灵活,是生产环境中比较推荐的使用方式。
首先需要安装这个库,安装命令是pip install flask-compress,安装完成后只需要在Flask应用中初始化该扩展即可。
from flask import Flask
from flask_compress import Compress
app = Flask(__name__)
# 初始化压缩扩展
compress = Compress()
compress.init_app(app)
# 可以自定义配置
app.config['COMPRESS_LEVEL'] = 6
app.config['COMPRESS_MIN_SIZE'] = 500
app.config['COMPRESS_MIMETYPES'] = ['text/html', 'text/css', 'application/json', 'application/javascript']
@app.route('/api/third_party_data')
def get_third_party_data():
data = {'result': '第三方库压缩数据' * 1200}
return data
if __name__ == '__main__':
app.run(debug=True)
不同实现方式的对比
三种实现方式各有优劣,我们可以根据实际场景选择:
| 实现方式 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| 内置压缩中间件 | 无需额外依赖,配置简单 | 功能较少,兼容性有限 | 简单项目,对压缩要求不高 |
| 自定义Gzip中间件 | 灵活度高,可完全自定义逻辑 | 需要自己处理边界情况,维护成本高 | 有特殊压缩需求,老版本Flask项目 |
| flask-compress第三方库 | 功能完善,配置灵活,稳定性高 | 需要额外安装依赖 | 生产环境,复杂项目 |
注意事项
- 压缩等级不是越高越好,等级过高会消耗大量CPU资源,反而可能降低接口性能,建议根据实际测试选择6左右的等级。
- 不要对已经压缩过的资源(比如图片、视频、zip包)再次进行Gzip压缩,这样不仅不会减小体积,还会浪费CPU资源。
- 需要设置合理的最小压缩大小阈值,太小的响应体压缩后可能体积反而变大,通常设置为500字节以上比较合适。
- 如果接口返回的是流式数据,不建议使用Gzip压缩,因为流式数据无法提前计算总长度,压缩处理会比较复杂。
响应压缩是接口优化的有效手段,但需要结合业务场景合理使用,避免过度压缩带来的性能损耗。在生产环境使用前,建议对不同压缩方案进行压测,选择最优的配置。