做过内容型产品的人都知道,图片处理这块"小事"能吃掉大量工程时间。用户上传一张 5MB 原图,手机端要 400px 宽的 WebP 缩略图,桌面端要 1200px 的 JPEG,海外用户还希望把图片里的中文说明翻译成英文——每一条需求背后都是一套裁剪、转换、存储、缓存逻辑。ImgFlux v0.1 把这些能力打包成一个读写分离的微服务,Docker Compose 一键拉起,存储后端随业务切换。
图片基础设施的真实痛点
一个典型的内容平台,图片处理链路至少涉及三件事:
- 多终端适配:同一张原图,至少要产出 3-5 种尺寸/格式变体,且要在请求时实时生成或从缓存命中。
- 存储后端迁移:初创团队用 MinIO 自建,上了规模切 AWS S3,国内业务又要对接阿里云 OSS——每次迁移都是一轮接口重写。
- 跨国内容本地化:商品图、海报上的文字需要 OCR 提取再翻译,这往往是一个完全独立的管线,和图片存储割裂。
ImgFlux 把上传写入、实时缩放读取、OCR 翻译三条线统一到一个服务里,用读写分离架构让各环节可以独立扩缩容。
读写分离架构怎么切
ImgFlux 将图片处理分成写通道(上传、OCR)和读通道(缩放、格式转换、分发):
- 写通道负责接收原图上传、持久化到存储后端、触发 OCR 任务。写入频率低但单次 payload 大,适合少量高配置实例。
- 读通道负责实时缩放和格式转换,请求频率高但单次处理轻,适合水平扩展大量小实例。
这种切分的好处是:读流量暴涨时只扩读节点,写通道不受干扰;OCR 任务慢时只加写节点,不会拖慢缩放响应。
多存储后端:MinIO / S3 / OSS 一行配置切换
ImgFlux 抽象了存储适配层,三种后端用同一个环境变量组控制。切换存储不需要改代码,只改部署配置:
# docker-compose.yml — MinIO 自建模式
services:
imgflux-write:
image: imgflux:v0.1
environment:
- STORAGE_BACKEND=minio
- MINIO_ENDPOINT=http://minio:9000
- MINIO_ACCESS_KEY=minioadmin
- MINIO_SECRET_KEY=minioadmin
- MINIO_BUCKET=imgflux
ports:
- "8081:8081"
imgflux-read:
image: imgflux:v0.1
environment:
- STORAGE_BACKEND=minio
- MINIO_ENDPOINT=http://minio:9000
- MINIO_ACCESS_KEY=minioadmin
- MINIO_SECRET_KEY=minioadmin
- MINIO_BUCKET=imgflux
- READ_PORT=8082
ports:
- "8082:8082"
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
ports:
- "9000:9000"
- "9001:9001"
volumes:
- minio_data:/data
volumes:
minio_data:
切到 AWS S3 时,只需要把 STORAGE_BACKEND 改为 s3,换上 S3 的 endpoint 和凭证,去掉 MinIO 服务块:
# 切换到 AWS S3 — 只改环境变量
environment:
- STORAGE_BACKEND=s3
- S3_REGION=ap-southeast-1
- S3_BUCKET=imgflux-prod
- AWS_ACCESS_KEY_ID=AKIAxxxxxxxx
- AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxx
阿里云 OSS 同理,STORAGE_BACKEND=oss,填入 endpoint 和 access key。迁移时读通道可以逐步切到新后端,写通道保持旧后端接收上传,做到灰度切换不停服。
实时缩放:URL 参数驱动,零预生成
ImgFlux 的缩放不是上传时预生成所有变体,而是通过 URL 参数实时裁剪。这意味着你永远不需要维护一个"缩略图生成任务队列":
# 上传原图(写通道)
curl -X POST http://localhost:8081/upload \
-F "image=@product-photo.jpg"
# 返回: {"image_id": "abc123", "original_url": "..."}
# 实时获取 400px 宽 WebP 缩略图(读通道)
curl http://localhost:8082/image/abc123?w=400&format=webp \
--output thumb_400.webp
# 桌面端要 1200px JPEG
curl http://localhost:8082/image/abc123?w=1200&format=jpeg \
--output desktop_1200.jpg
前端直接拼 URL 参数就能拿到适配尺寸,不需要后端预判所有场景。首次请求时读通道从存储拉原图、裁剪、转换格式并返回,同时缓存结果;后续相同参数的请求直接命中缓存。
OCR 翻译管线:从图片提取文字到多语言输出
跨国业务场景里,商品图上的中文标签、海报里的活动说明都需要翻译。ImgFlux 在写通道集成了 OCR + 翻译流程:
# 上传并触发 OCR 翻译
curl -X POST http://localhost:8081/upload \
-F "image=@poster-with-chinese-text.jpg" \
-F "ocr=true" \
-F "translate_to=en"
# 返回:
# {
# "image_id": "def456",
# "ocr_result": {
# "source_text": "限时优惠 买二送一",
# "translated_text": "Limited time offer: Buy 2 Get 1 Free",
# "source_lang": "zh",
# "target_lang": "en"
# }
# }
OCR 和翻译在写通道异步执行,不阻塞上传响应。翻译结果通过 API 查询获取,也可以配置回调推送到业务系统。
部署建议与边界
起步阶段,用 Docker Compose + MinIO 最省事,一台机器就能跑全套。上面的 compose 文件直接 docker compose up -d 即可启动,适合内部工具、小型 CMS、MVP 产品。
规模增长时,把读写通道拆到不同主机组,读通道按流量水平扩展,存储切到 S3 或 OSS 享受托管服务的持久性和 CDN 加速。OCR 翻译如果量不大,可以和写通道共用实例;量大时单独抽出来做异步 worker。
需要注意的边界:
- 实时缩放依赖原图从存储后端拉取,首次请求延迟 = 网络读取 + 裁剪处理。对延迟敏感的场景可以在上传后预热常用尺寸。
- OCR 翻译精度取决于底层 OCR 引擎和翻译服务,复杂排版(多列、手写体)识别率会下降,建议对结果做人工审核或置信度过滤。
- 当前 v0.1 版本聚焦核心管线,高级功能(水印、智能裁剪焦点、批量导入)还在路线图上,选型时确认这些是否是硬需求。
如果你正在为图片处理搭基础设施,ImgFlux v0.1 提供了一个最小可用的起点——一个 compose 文件、两个端口、三种存储后端,比从零拼凑上传+裁剪+存储+OCR 四套服务省出至少两周工期。