如何在Flask中高效处理8万张商品图片批量再生的大型任务
Flask CLI批量图片水印处理落地方案
1. 前置准备:幂等性与可追溯设计
- 提前在数据库中创建水印处理任务表,核心字段包括:图片唯一ID、原图存储路径、水印图目标路径、处理状态(待处理/处理中/处理成功/处理失败)、重试次数、失败原因、更新时间。所有处理逻辑基于任务表执行,避免重复处理、中断后无法续跑的问题。
- 处理前全量备份所有原图,避免操作失误导致原始资源损坏;先小范围抽测100~200张图片,确认水印大小、位置、透明度符合业务要求后再启动全量任务。
2. Flask CLI命令核心实现
核心逻辑要避免内存溢出、单张图错误导致全流程崩溃的问题,参考实现如下:
import click from flask import current_app from flask.cli import with_appcontext from your_app import db from your_app.models import GoodsImage from your_app.utils import generate_watermark_img @click.command("batch_gen_watermark") @click.option("--batch_size", default=200, help="单批次处理图片数量") @click.option("--max_retry", default=3, help="单张图片最大重试次数") @with_appcontext def batch_gen_watermark(batch_size, max_retry): offset = 0 success_count = 0 fail_count = 0 while True: # 游标分页拉取任务,避免一次性加载全量数据占满内存 pending_tasks = GoodsImage.query.filter( GoodsImage.watermark_status.in_(["pending", "failed"]), GoodsImage.retry_count < max_retry ).limit(batch_size).offset(offset).all() if not pending_tasks: click.echo(f"任务全部结束,成功:{success_count} 张,失败:{fail_count} 张") break for task in pending_tasks: try: task.watermark_status = "processing" db.session.commit() # 执行水印生成逻辑,支持本地/对象存储读写 generate_watermark_img(task.origin_img_url, task.target_watermark_url) task.watermark_status = "success" success_count += 1 except Exception as e: task.watermark_status = "failed" task.retry_count += 1 task.fail_reason = str(e)[:255] fail_count += 1 finally: db.session.commit() offset += batch_size click.echo(f"已处理{offset}张,当前成功率:{round(success_count/offset*100, 2)}%")
写完命令后在Flask应用中注册CLI命令,即可通过flask batch_gen_watermark启动任务。
3. 性能与资源管控优化
- 图片处理是CPU密集型任务,推荐用
concurrent.futures.ProcessPoolExecutor做多进程处理,进程数设置为服务器CPU核心数的1~1.5倍即可,不要占满CPU影响线上业务;如果用云服务器可以临时升配CPU核心数,处理完再降配。 - 提前将水印模板加载到内存,不要每张图片都重新读取水印文件,减少不必要的IO开销。
- 如果图片存储在对象存储中,优先用内网Endpoint读写,避免公网带宽限制;如果跑任务的服务器和业务服务器是同一台,可以加限速逻辑,比如每秒最多处理20张,或者只在凌晨业务低峰期运行,避免占用带宽影响用户访问。
- 任务支持随时终止,下次启动时会自动筛选未完成的任务续跑,不需要额外开发暂停逻辑。
4. 异常处理与监控
- 所有失败任务都会记录失败原因,全量任务跑完后可以导出所有失败的记录,针对性排查问题(比如原图损坏、存储权限不足等)后手动触发重跑。
- 如果图片量还在持续增长,可以引入分布式任务队列拆分任务到多台机器并行处理,只要保证不同节点拉取的任务不重复即可。
内容的提问来源于stack exchange,提问作者Fathey Abdel slam
相关产品推荐
相关产品推荐

