All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m35s
- 受控系统配置要求 Key 至少三段,原两段式 Key(如 polling.rate_limit_mode)注册被拒,后台不可见、限流器只能使用默认值 - Key 改为 polling.gateway.* 与 polling.stop_resume_record.*;新增迁移 000247 将已落库的旧 Key 改名并保留取值 - 后续提案中规划的开关同步改为三段式(polling.scheduler.mode、polling.stop_resume.queue_enabled)
5.5 KiB
5.5 KiB
Why
上游按运营商账户限频,本系统却只有"全局 + 任务类型"的并发计数,数值没有依据,且自动停复机、业务事件观测完全不受约束。生产 2026-10-22:退款触发的停机 24 小时失败约 26.8 万次、单卡每 1~2 秒调用一次;轮询失败约 37 万次但失败原因全部为空,无法区分限频、卡错误与超时。本 Change 是《轮询按运营商账户限流技术方案》(docs/engineering/轮询按运营商账户限流技术方案.md)第五部分第 3 节的第 1 步:不动现有调度,先给网关调用加上按运营商账户的限流,并让失败原因与调用量可见,作为后续各 Change 和各账户 QPS 配置的依据。
What Changes
- 新增网关限流器:按"运营商账户 → 限流组 → 操作"对卡的 5 个网关操作(查流量、查状态、查实名、停机、复机)做每秒请求数限制,滑动窗口,跨 Worker 共享;按每次实际 HTTP 尝试计量(挂在
AttemptObserver.BeforeAttempt),网关内部重试同样计入。 - 默认限流、显式豁免:只有后台人工点击停复机、通道阈值、自动续费、手动刷新 4 个入口打豁免标记,其余卡操作一律受限。
- 限流组配置(新表
tb_carrier_rate_limit_group):组内操作、max_qps、高优先级操作与预留额度、可选全局组;未覆盖或组已停用的操作按默认 QPS,不存在不限流的自动调用。 - 两种模式:受控系统配置
polling.gateway.rate_limit_mode,observe(只统计、不拦截,默认)与enforce(拦截),全局生效、不按账户覆盖。上线先observe采集至少一周,配好全部账户限流组后整体切到enforce。 - 拦截时在 Asynq 任务内不等待:拿不到名额立即返回"限流"错误;轮询任务短延迟重入队且不计失败;Asynq 服务配置
IsFailure对"限流"错误返回 false、RetryDelayFunc返回固定短延迟,Outbox 消费者与观测序列因此不会因限流消耗重试次数、推迟数小时或归档。 - BREAKING
StopCard/StartCard不再使用网关内部重试(maxRetries = 0),对全部停复机入口生效(含后台人工点击):避免超时后几百毫秒内对同一张卡连发 2~3 次撞上游单卡频率限制。 - 网关返回结构化错误(错误类别、网关业务码与信息、耗时),不再只拼在错误字符串里。
- 上游错误分类:新表
tb_gateway_error_classification(关键字 → 类别:频率限制 / 终态不可操作 / 已是目标状态 / 临时故障 / 业务错误 / 账户配置错误),后台可增补,提供测试接口。只有明确返回已是目标状态才视为成功。 - 停复机记录:新表
tb_card_stop_resume_record(按月分区 + DEFAULT 分区,提前建未来分区),每次实际调用上游停机或复机写一条;BREAKING 系统自动停复机不再写统一审计tb_audit_event与集成日志tb_integration_log(后台人工点击仍写统一审计);轮询查询不再写集成日志。 - 查询类调用不逐条落库:Redis 按"运营商账户 × 操作 × 结果类别"做分钟级计数与耗时分布。
- 后台接口:限流组增删改查、错误分类增删改查与测试、停复机记录查询、按账户调用量统计、
polling模块系统配置注册(含 JSON 结构校验)、枚举选项。
Capabilities
New Capabilities
carrier-gateway-rate-limit:按运营商账户的网关限流、计量口径、豁免、只统计与拦截模式、限流组配置、Asynq 任务遇限流的重试语义、停复机不做网关内部重试。gateway-call-observability:网关结构化错误、上游错误分类、停复机记录表、查询调用分钟计数、按账户调用量与失败查询接口。
Modified Capabilities
polling-load-control:"业务变化与轮询异常仍可追溯"改为:系统自动停复机写停复机记录表而非统一审计与集成日志;查询失败以分钟计数与卡上最近错误保留可调查信息,不逐条写集成日志。
Impact
- 依赖:无前置 Change;不改现有轮询调度、并发计数与停复机业务规则。
- 数据库:新增
tb_carrier_rate_limit_group、tb_gateway_error_classification、tb_card_stop_resume_record(分区表);tb_system_config插入module = polling配置项。均为新的成对迁移。 - 代码:
internal/gateway/client.go、internal/gateway/flow_card.go;新增限流器与错误分类器;pkg/queue/server.go(IsFailure、RetryDelayFunc);internal/task/polling_*_handler.go(限流重入队);internal/service/iot_card/stop_resume_service.go与stop_resume_audit.go(记录表替代审计);internal/infrastructure/systemconfig注册;新增 Handler / 路由 / DTO 并同步cmd/api/docs.go、cmd/gendocs/main.go。 - 接口:新增
/polling-rate-limit-groups、/gateway-error-classifications、/card-stop-resume-records、/iot-cards/:id/stop-resume-records、/polling-stats/carriers、/polling-options;/system-configs的module枚举增加polling。前端需新增限流组、错误分类、停复机记录页面,系统配置页增加polling模块。 - 行为:后台人工点击停复机遇网络超时不再自动重试,页面直接显示失败;系统自动停复机的审计查询改到停复机记录。
- 运营:
observe期间按调用量统计为全部运营商账户配置限流组,确认后切enforce。