9.6 KiB
队列接口 v1
状态:已实现创建、查询、配置替换、暂停/恢复、共享并发、开始速率与未终结任务背压。MySQL 是跨节点额度的权威存储;没有额外缓存或消息队列依赖。
POST /v1/queues
需要 queues:manage 和当前命名空间内全部队列范围。鉴权、请求体、幂等键及错误信封与 任务接口 一致。
| 字段 | 类型 | 要求 |
|---|---|---|
| name | string | 1–128 字符,以 ASCII 字母/数字开头,其后允许字母、数字、_ . : -;命名空间内唯一 |
| max_concurrency | uint32 | 必填,1–100000 |
| rate_per_second | uint32 | 必填,1–1000000 |
| max_unfinished_tasks | uint32 | 可选,省略/零为 100000;有效范围 1–1000000,包含待核查任务 |
curl "$ORBIT_URL/v1/queues" \
-H "Authorization: Bearer $ORBIT_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: queue-images-v1' \
--data '{"name":"images","max_concurrency":8,"rate_per_second":100}'
首次 201:
{
"request_id":"44444444444444444444444444444444",
"data":{
"deduplicated":false,
"queue":{
"id":"11111111111111111111111111111111",
"namespace_id":"33333333333333333333333333333333",
"name":"images","paused":false,"max_concurrency":8,"rate_per_second":100,
"max_unfinished_tasks":100000,"unfinished_tasks":"0","revision":"1"
}
}
}
同键同内容返回 200、deduplicated=true。同键不同内容返回 409 IDEMPOTENCY_CONFLICT;换键创建同名队列返回 409 STATE_CONFLICT。创建、幂等记录和管理审计同事务提交。
SDK:Client.CreateQueue(ctx, key, orbit.CreateQueueRequest{...})。
GET /v1/queues/{queue_id}
权限:queues:read 和对应队列范围。200 的 data 直接为上方 queue 对象;资源不存在或单资源范围不匹配返回 404。
curl "$ORBIT_URL/v1/queues/$ORBIT_QUEUE_ID" -H "Authorization: Bearer $ORBIT_TOKEN"
SDK:Client.GetQueue(ctx, queueID)。范围限制、重复创建和同名冲突已纳入 P1 回归。这些配置上限不是生产容量承诺。
unfinished_tasks 为 uint64 的十进制字符串,表示当前 WAITING、LEASED、RUNNING、NEEDS_REVIEW 的总数。它是运行计数,变化不增加队列配置 revision。创建/配置回执保存操作时的快照,获取实时积压需要再次 GetQueue。
POST /v1/queues/{queue_id}:configure
需要 queues:manage 及对应队列范围。完整替换控制参数,不改变名称、队列身份、已受理任务的冻结策略或历史结果。
| 字段 | 类型 | 要求 |
|---|---|---|
| expected_revision | string | 必填,非零 uint64 的十进制字符串 |
| reason | string | 必填,非空白,最多 1024 个 Unicode 字符,写入审计 |
| paused | bool | 必须显式提供;省略/null 都拒绝 |
| max_concurrency | uint32 | 必填,1–100000 |
| rate_per_second | uint32 | 必填,1–1000000 |
| max_unfinished_tasks | uint32 | 必填,1–1000000;配置命令不使用零值默认 |
curl "$ORBIT_URL/v1/queues/$ORBIT_QUEUE_ID:configure" \
-H "Authorization: Bearer $ORBIT_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: queue-control-001' \
--data '{"expected_revision":"1","reason":"limit background traffic","paused":false,"max_concurrency":2,"rate_per_second":1,"max_unfinished_tasks":100}'
成功 200 的 data 形状与创建一致,队列配置 revision 加一。配置、并发限制同步、审计、事件和幂等回执在一个事务提交。原键、原 expected_revision 和原内容重报返回原快照,deduplicated=true;同键不同内容为 409 IDEMPOTENCY_CONFLICT,新键使用旧版本为 409 STATE_CONFLICT。权限每次重新检查。
SDK:Client.ConfigureQueue(ctx, queueID, key, orbit.ConfigureQueueRequest{...}) 返回 CreateQueueResult。先 GetQueue 读取版本,网络结果不明时保留原命令核对;只有确认版本冲突并重新评估后,才建立新的配置操作。
并发、限速与背压的区别
| 控制 | 实际行为 |
|---|---|
| paused=true | 阻止新的领取和 Start;继续受理任务、计划生成、续租、结果确认、取消及恢复 |
| max_concurrency | 限制队列有效执行许可,包括 LEASED 和 RUNNING;许可在结果/取消/恢复事务中释放 |
| rate_per_second | 每个数据库一秒计数窗口内最多提交的 Start 授权数;续租和原回执重报不计数 |
| max_unfinished_tasks | 限制新任务进入队列;等待、退避、预占、运行、待核查都占一个名额 |
速率窗口由第一次成功 Start 建立,保存到 MySQL;所有节点共享。窗口结束后的下一次 Start 建立新窗口。一次窗口内可突发至设定值,窗口交界附近可能出现接近两倍的短时突发;这不是“任意滑动一秒”的承诺,也不限制业务处理器内部发出请求的速率。开始授权成功不证明外部业务效果已经发生。
领取还预留尚未开始尝试所需的窗口空间,额度不足时保持 WAITING,不创建额外尝试。若领取后管理员降低速率,Start 可返回 WS RATE_LIMITED;不批准开始、不写回执、不增加尝试次数。自动 SDK 在同一租约内按原消息身份退避核对,底层客户端也必须遵守剩余租约,不能绕过开始授权执行。限流不延长总截止、开始截止或尝试预算。
降并发不撤销已有许可,超出新上限时等待在途工作收尾再领取;降速率保留当前窗口已用次数;降积压上限保留已有任务,禁止新受理直到低于新上限。调整参数、暂停/恢复、断开连接和节点重启都不能清零使用量。
任务第一次进入 SUCCEEDED、FAILED 或 CANCELLED 时,积压额度同事务减一;重试和待核查不释放、不重复增加。运行中取消只保存意图,仍占名额。迟到证据及重复确认不改变计数。人工核查解除入口仍待 P5,不能为了释放额度把未知结果改成成功/取消。
HTTP 429 QUEUE_FULL
满额时新的 Submit 返回 429,Retry-After: 1,错误信封为:
{"request_id":"44444444444444444444444444444444","error":{"code":"QUEUE_FULL","message":"queue unfinished task limit reached; retry later using the original identity"}}
该请求没有受理任务,新增占位幂等记录也回滚。已受理请求的同身份重报优先返回原回执,不被当前满额拒绝。释放空间后使用被拒请求的原键、原内容有限重试;建议至少等待 Retry-After 并加入抖动/总截止。若绝对 available_at/start_deadline_at 已过期,原请求会被参数规则拒绝,不能无限重试。
SDK 返回 *orbit.APIError,Code=QUEUE_FULL、StatusCode=429、RetryAfter=time.Second。RetryAfter 解析服务端整数秒建议,缺失/无效/超过一小时为零;SDK 不自动重报业务写请求。取消、查询、结果上报和管理配置不受受理满额限制。
计划触发也使用相同名额。部分补跑已生成的任务正常提交;满额的原触发点保留为下一游标,不创建假任务或跳过记录。下一批继续使用冻结的漏跑策略,因此等待期间超过补偿窗口的点仍可能按策略记录 SKIPPED。队列暂停仅控制执行,要停止计划生成应另外暂停计划。
完整 SDK 场景
源码:resources/main.go。先完成当前迁移并启动服务,初始化带 Worker 权限且 queues:manage 范围为全部队列的专用开发凭据:
mkdir -p .local
chmod 700 .local
go run ./cmd/orbit-admin bootstrap \
--application resources-demo --namespace default --environment development \
--queue bootstrap --worker-access --output .local/resources.credentials.json
cd sdk/go
ORBIT_URL=http://127.0.0.1:8080 \
ORBIT_CREDENTIALS_FILE=../../.local/resources.credentials.json \
go run ./examples/resources
示例创建独立队列(积压 2、并发 2、每秒 1 次开始),暂停后提交两个任务;第三个被拒,重复第一个仍得到原回执;取消第一个释放空间,用第三个原身份重新提交,然后恢复并执行两个纯数据回显任务。
backpressure=QUEUE_FULL http=429
duplicate=true rejected_request_retried=true
task=<第二个任务ID> state=SUCCEEDED attempts=1
task=<第三个任务ID> state=SUCCEEDED attempts=1
unfinished=0 rate_per_second=1 worker_drained=true
每次运行创建独立队列和任务,历史保留,不硬删除。无外部业务副作用;任务自带 20 秒总截止,失败非零退出并有界收尾。示例遇到未知网络结果会退出,不自动换键重建资源。
升级与未完成范围
000009 增加四个带中文说明的队列字段,回填所有既有未终结任务;旧配置版本及任务内容保持不变。先停止旧服务和写入,运行迁移,再启动新版。只读检查不能代替升级维护窗口;大表回填及混合版本升级待生产环境验证。
创建命令省略新字段时,幂等摘要保留旧字段集合。旧创建回执不含新字段,SDK 解码为零,只表示历史快照缺少信息,实时配置另行 GetQueue。配置接口是新能力;自动 SDK 已能处理 RATE_LIMITED,进行降额管理前应先升级 Worker。
本阶段验证见 资源控制报告。应用级跨命名空间配额 已实现并同时生效。资源键许可 与 优先级/节点公平派发 已实现;可靠事件积压限制及跨节点公平负载和容量验收继续推进。