跳转到主要内容
本页是一篇技术分享 / 建议篇,面向需要把图片生成接入到自己产品里的开发团队。我们只提供工程实践思路,不涉及任何需要 API易 侧改造的功能——你完全可以基于现有的同步接口落地。

同步还是异步?先理解 API易 的接口模型

API易 的图片生成全部是同步接口/v1/images/generations 等端点「请求一旦提交就会跑到结束」。客户端即使中途断开连接,服务端仍会把这次出图完整执行完——也就是说,它不是「先拿一个 task_id、再轮询结果」的异步任务接口。
API易 在网关层已经把上游的异步 polling(部分服务商官方走 polling_url 轮询)封装成了同步的 OpenAI Images API。对你而言永远是「一次提交、一次拿结果」,不需要自己写轮询循环
很多团队第一反应是:「那我怎么做异步任务管理?」——这其实是两件事:
  • 同步:是 API易 接口的形态(HTTP 请求级别,发一次拿一次)。
  • 异步队列:是你这一侧的工程实践(业务任务级别,提交即返回、后台慢慢跑)。
两者并不冲突。下面讲的,就是如何在同步接口之上,自己包一层异步队列。

为什么开发团队仍然需要「任务式」管理

直接在用户请求线程里同步调一次图片 API,对 Demo 足够;但一旦面向 C 端用户、要做产品,你几乎一定需要把「业务任务」和「单次 HTTP 调用」解耦。原因有四:

成功 ≠ 一次调用

一个「成功的任务」往往由多次同步调用拼成:首次超时、偶发 429/503 都需要重试。把任务和单次调用解耦后,重试、退避、超时都对最终用户透明——用户只看到「这张图最终成了」。

透明转发,不存输入输出

API易 只做透明转发,不存储用户的输入和输出(prompt、参考图、出图结果都不留底)。要给用户做历史记录、状态查询、结果留存,必须自己落库——这是产品侧绕不开的一步。

C 端体验更友好

用户提交即拿到 task_id,前端轮询任务状态而不是干等一条长连接。刷新页面、临时断网都不会丢任务;批量出图也能排队跑、逐个回填。

多服务商接入成为可能

一旦有了自己的任务抽象层,Worker 层就能按需切换/容灾/比价多个服务商——退一万步讲,这让「不把鸡蛋放一个篮子」成为可能。

参考架构:把同步调用包进异步队列

核心思路只有一句:API 层只负责”收任务、入队、返回 task_id”,真正的同步调用交给后台 Worker。
  C端/前端 ──①提交任务──▶  API 层  ──②入队──▶  队列 (Redis / MQ / DB 表)
      ▲                      │                              │
      │ ⑤轮询 task 状态        │ 立即返回 task_id               │ ③取任务
      │                      ▼                              ▼
      └──────────────────  数据库  ◀──④落库(状态/输入/输出URL)── Worker
                                                              │ 同步调用 API易
                                                              │ (带重试 / 退避)

                                                  api.apiyi.com (同步图片 API)
1

提交即返回

前端把出图请求发给你自己的 API 层;API 层创建一条任务记录(状态 pending)、写入队列,立即把 task_id 返回给前端。整个过程不阻塞用户,毫秒级返回。
2

入队

队列可以很轻:Redis List / Stream、RabbitMQ / Kafka,甚至一张带 status 字段的数据库表配合定时扫描都行。选型取决于你的量级,不必一上来就上重型中间件。
3

Worker 同步调用 + 重试

后台 Worker 从队列取任务,把状态置为 running同步调用 API易 图片接口。遇到可重试错误时按指数退避重试(见下文「重试与计费」),全程对用户透明。
4

落库

无论成功失败,都把结果写回数据库:成功则存输出图地址、耗时、计费元数据,状态置 succeeded;失败则存错误信息、状态置 failed这一步就是 API易 不替你做、必须自己做的部分。
5

前端轮询

前端拿着 task_id 周期性查任务状态(或用 WebSocket / SSE 推送)。任务完成就展示结果,失败就给出友好提示。用户的浏览器从头到尾不需要挂着一条长连接。

任务状态机与数据模型

建议用一个清晰的状态机来描述每个任务的生命周期:
状态含义典型流转
pending已入队,等待 Worker 领取running
runningWorker 正在同步调用 API易succeeded / retrying / failed
retrying命中可重试错误,等待退避后重试running
succeeded出图成功,结果已落库终态
failed重试用尽或不可重试错误终态
任务表建议至少记录以下字段(具体类型按你的技术栈而定):
字段说明
task_id任务唯一标识,提交时即返回给前端
status上表中的状态枚举
provider / model使用的服务商与模型(为多服务商预留)
input用户输入(prompt、参考图引用、尺寸等参数)
output_url出图结果地址(建议转存自有存储后的 URL)
retry_count已重试次数,用于限流与排查
error失败原因(错误码 + 友好文案)
created_at / updated_at创建与最近更新时间(建议带时区,如 UTC+8)
latency / cost耗时与计费元数据,便于成本核算与监控
出图结果建议转存到你自己的对象存储(OSS / S3 等)后再把 URL 落库,不要长期依赖第三方返回的临时链接——临时链接可能过期,自己存一份对 C 端展示更稳定。

重试与计费:哪些该重试,哪些不该

「任务式管理」最大的价值就是把重试做对。不同错误的计费与重试策略并不一样:
场景是否计费是否重试
429 / 503(限流 / 上游繁忙)不计费✅ 可重试,指数退避,建议 2 次
客户端超时主动断开仍计费⚠️ 可重试,但要先按分辨率设置合理超时(约 60–600s)
内容安全拒绝(状态码 200 仍计费)仍计费❌ 不应重试,应回传用户友好提示
把「业务任务的重试次数」和「是否产生计费」分开记账。429/503 重试不计费可以放心退避;但超时断开、内容安全拒绝即使「失败」也已计费——盲目重试会放大成本。重试前先判断错误类型,再决定要不要再花一次钱。
错误判定与友好提示的完整口径,见下面两篇:

Gemini 出图错误处理

出图失败的判断指标、内容审核政策与友好提示方案。

出图失败保障计划

非主观原因导致的失败,按条数核算后补发额度。

进阶:一套队列接多个服务商

有了任务抽象层,Worker 调用就可以从「写死调某个接口」变成「按 provider 路由」。统一一个 submit(provider, payload) 入口,Worker 按任务里的 provider 字段决定实际打到哪个上游:
  • 容灾:A 服务商连续失败时自动切到 B,对用户无感。
  • 比价 / 分流:按成本或场景把不同任务分给不同服务商或模型。
  • 灰度:新模型先放一小部分流量验证,再逐步放量。
多数情况下其实不需要自建多服务商层:API易 本身已聚合 gpt-image-2、Nano Banana、FLUX、Seedream 等多模型,一个 API易 Key 即可在同一接口风格下覆盖大部分需求。自建 provider 抽象层是「退一万步」的可选项——当你确实需要跨服务商容灾或比价时再上。

常见问题

图片出图本身就是「发一次、拿一张图」的强同步语义,封装成同步接口对绝大多数调用方最简单——不用维护轮询、不用处理 task 过期。是否需要异步队列、状态机、落库,取决于你的产品形态(是否面向 C 端、是否要历史记录),所以这部分留给你按需自建最灵活。
会继续跑。同步端点一旦收到请求就会执行到结束,客户端断开不会中止服务端出图,且这次出图照常计费。所以请按分辨率设置足够的超时(约 60–600s),不要把超时设得过短导致「白花钱还拿不到图」。
不会。API易 只做透明转发,不存储用户的输入和输出。要给用户提供历史记录、状态查询、结果留存,需要你在自己这一侧落库——这正是本文建议「任务式管理」的核心原因。
多数情况不需要。API易 已经在一个接口风格下聚合了多家模型,一个 Key 通常够用。只有当你有跨服务商容灾、比价、合规分流等明确诉求时,再考虑在 Worker 层加 provider 抽象——这是可选项,不是必需项。

相关文档

FLUX 概览

上游异步 polling 被封装成同步 OpenAI Images API 的实例。

Nano Banana 开发指南

同步多线程调用、超时设置与计费基础一站式说明。

Gemini 出图错误处理

出图失败的判断指标与友好提示方案。

出图失败保障计划

非主观原因失败的额度补发规则。