All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m33s
- 新增网关限流:按本系统运营商账户(卡 carrier_id)→ 限流组 → 操作限制每秒请求数,每次 HTTP 尝试计量,默认限流、仅后台人工点击/通道阈值/自动续费/手动刷新豁免;支持只统计与拦截两种模式,默认只统计 - Asynq 遇限流不计失败、固定短延迟重试;轮询任务与停复机业务重试遇限流短延迟重排 - 停机、复机不再使用网关内部重试,只发一次请求 - 网关返回结构化错误;新增上游错误分类规则表与测试接口 - 新增按月分区的停复机记录表:系统自动停复机只写记录,不再写统一审计与集成日志;普通轮询查询不再写集成日志 - 新增限流组、错误分类、停复机记录、按账户调用统计与枚举后台接口 - 迁移 000243~000246;同步 OpenSpec 提案(含后续 6 个 change)与技术方案、工程约束
244 lines
9.4 KiB
Go
244 lines
9.4 KiB
Go
package constants
|
||
|
||
import (
|
||
"fmt"
|
||
"time"
|
||
)
|
||
|
||
// 卡网关操作:限流组、错误分类与调用统计共用的操作标识。
|
||
const (
|
||
// GatewayOpQueryFlow 查流量。
|
||
GatewayOpQueryFlow = "query_flow"
|
||
// GatewayOpQueryStatus 查卡状态。
|
||
GatewayOpQueryStatus = "query_status"
|
||
// GatewayOpQueryRealname 查实名。
|
||
GatewayOpQueryRealname = "query_realname"
|
||
// GatewayOpStop 停机。
|
||
GatewayOpStop = "stop"
|
||
// GatewayOpStart 复机。
|
||
GatewayOpStart = "start"
|
||
)
|
||
|
||
// GatewayCardOperations 是受运营商账户限流约束的卡网关操作全集。
|
||
var GatewayCardOperations = []string{GatewayOpQueryFlow, GatewayOpQueryStatus, GatewayOpQueryRealname, GatewayOpStop, GatewayOpStart}
|
||
|
||
// GatewayOperationName 返回卡网关操作的中文名称。
|
||
func GatewayOperationName(op string) string {
|
||
switch op {
|
||
case GatewayOpQueryFlow:
|
||
return "查流量"
|
||
case GatewayOpQueryStatus:
|
||
return "查状态"
|
||
case GatewayOpQueryRealname:
|
||
return "查实名"
|
||
case GatewayOpStop:
|
||
return "停机"
|
||
case GatewayOpStart:
|
||
return "复机"
|
||
default:
|
||
return "未知"
|
||
}
|
||
}
|
||
|
||
// IsGatewayCardOperation 判断是否为合法的卡网关操作。
|
||
func IsGatewayCardOperation(op string) bool {
|
||
for _, item := range GatewayCardOperations {
|
||
if item == op {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// 网关调用错误类别(结构化错误与分钟计数共用)。
|
||
const (
|
||
// GatewayErrorNetwork 网络错误(连接失败、DNS 等)。
|
||
GatewayErrorNetwork = "network"
|
||
// GatewayErrorTimeout 请求超时,结果未知。
|
||
GatewayErrorTimeout = "timeout"
|
||
// GatewayErrorHTTP HTTP 状态码异常。
|
||
GatewayErrorHTTP = "http"
|
||
// GatewayErrorInvalidResponse 响应无效。
|
||
GatewayErrorInvalidResponse = "invalid_response"
|
||
// GatewayErrorUpstream 上游业务错误(再经错误分类细分)。
|
||
GatewayErrorUpstream = "upstream"
|
||
// GatewayErrorRateLimited 本系统限流拒绝,未发出请求。
|
||
GatewayErrorRateLimited = "rate_limited"
|
||
// GatewayResultSuccess 调用成功(计数用)。
|
||
GatewayResultSuccess = "success"
|
||
)
|
||
|
||
// 上游错误分类类别(tb_gateway_error_classification.category)。
|
||
const (
|
||
// GatewayClassRateLimitedUpstream 上游频率限制。
|
||
GatewayClassRateLimitedUpstream = "rate_limited_upstream"
|
||
// GatewayClassTerminal 上游终态不可操作。
|
||
GatewayClassTerminal = "terminal"
|
||
// GatewayClassAlreadyTarget 上游表示卡已是目标状态。
|
||
GatewayClassAlreadyTarget = "already_target"
|
||
// GatewayClassTransient 上游临时故障。
|
||
GatewayClassTransient = "transient"
|
||
// GatewayClassBusiness 上游业务错误(未命中规则的默认类别)。
|
||
GatewayClassBusiness = "business"
|
||
// GatewayClassAccountConfig 账户配置错误(凭证、接入参数)。
|
||
GatewayClassAccountConfig = "account_config"
|
||
)
|
||
|
||
// GatewayErrorClasses 是上游错误分类类别全集。
|
||
var GatewayErrorClasses = []string{GatewayClassRateLimitedUpstream, GatewayClassTerminal, GatewayClassAlreadyTarget, GatewayClassTransient, GatewayClassBusiness, GatewayClassAccountConfig}
|
||
|
||
// GatewayErrorClassName 返回上游错误分类类别中文名称。
|
||
func GatewayErrorClassName(class string) string {
|
||
switch class {
|
||
case GatewayClassRateLimitedUpstream:
|
||
return "上游频率限制"
|
||
case GatewayClassTerminal:
|
||
return "终态不可操作"
|
||
case GatewayClassAlreadyTarget:
|
||
return "已是目标状态"
|
||
case GatewayClassTransient:
|
||
return "临时故障"
|
||
case GatewayClassBusiness:
|
||
return "业务错误"
|
||
case GatewayClassAccountConfig:
|
||
return "账户配置错误"
|
||
default:
|
||
return "未知"
|
||
}
|
||
}
|
||
|
||
// 错误分类匹配方式。
|
||
const (
|
||
// GatewayMatchContains 包含关键字。
|
||
GatewayMatchContains = "contains"
|
||
// GatewayMatchPrefix 以关键字开头。
|
||
GatewayMatchPrefix = "prefix"
|
||
// GatewayMatchRegex 正则匹配。
|
||
GatewayMatchRegex = "regex"
|
||
)
|
||
|
||
// 限流豁免来源:只有这 4 个入口可以绕过运营商账户限流。
|
||
const (
|
||
// RateLimitExemptManualClick 后台人工点击停复机。
|
||
RateLimitExemptManualClick = "manual_click"
|
||
// RateLimitExemptChannelThreshold 通道阈值停复机。
|
||
RateLimitExemptChannelThreshold = "channel_threshold"
|
||
// RateLimitExemptAutoRenewal 自动续费停复机。
|
||
RateLimitExemptAutoRenewal = "auto_renewal"
|
||
// RateLimitExemptManualRefresh 手动刷新。
|
||
RateLimitExemptManualRefresh = "manual_refresh"
|
||
)
|
||
|
||
// 限流模式(polling.rate_limit_mode)。
|
||
const (
|
||
// RateLimitModeObserve 只统计不拦截。
|
||
RateLimitModeObserve = "observe"
|
||
// RateLimitModeEnforce 拦截。
|
||
RateLimitModeEnforce = "enforce"
|
||
)
|
||
|
||
// 轮询模块受控系统配置。
|
||
const (
|
||
// SystemConfigModulePolling 是轮询与网关限流配置模块。
|
||
SystemConfigModulePolling = "polling"
|
||
// SystemConfigPollingRateLimitMode 网关限流模式。
|
||
SystemConfigPollingRateLimitMode = "polling.rate_limit_mode"
|
||
// SystemConfigPollingGatewayDefaultQPS 默认每秒请求上限。
|
||
SystemConfigPollingGatewayDefaultQPS = "polling.gateway_default_qps"
|
||
// SystemConfigPollingRateLimitedRetryDelay Asynq 任务遇限流后的固定重试延迟(秒)。
|
||
SystemConfigPollingRateLimitedRetryDelay = "polling.rate_limited_retry_delay_seconds"
|
||
// SystemConfigPollingRateLimitDeferAlert 限流累计推迟告警阈值(秒)。
|
||
SystemConfigPollingRateLimitDeferAlert = "polling.rate_limit_defer_alert_seconds"
|
||
// SystemConfigPollingStopResumeRecordRetention 停复机记录保留月数。
|
||
SystemConfigPollingStopResumeRecordRetention = "polling.stop_resume_record_retention_months"
|
||
// SystemConfigPollingStopResumeRecordPremake 停复机记录提前建分区月数。
|
||
SystemConfigPollingStopResumeRecordPremake = "polling.stop_resume_record_premake_months"
|
||
)
|
||
|
||
// TaskTypeStopResumeRecordPartition 停复机记录分区维护定时任务(每日执行,使用数据清理队列)。
|
||
const TaskTypeStopResumeRecordPartition = "stop_resume_record:partition"
|
||
|
||
// 停复机记录动作与结果(tb_card_stop_resume_record)。
|
||
const (
|
||
// StopResumeActionStop 停机。
|
||
StopResumeActionStop = "stop"
|
||
// StopResumeActionStart 复机。
|
||
StopResumeActionStart = "start"
|
||
// StopResumeRecordSuccess 成功。
|
||
StopResumeRecordSuccess = "success"
|
||
// StopResumeRecordFailed 失败。
|
||
StopResumeRecordFailed = "failed"
|
||
// StopResumeRecordUnknown 结果未知。
|
||
StopResumeRecordUnknown = "unknown"
|
||
// StopResumeRecordAlreadyTarget 已是目标状态。
|
||
StopResumeRecordAlreadyTarget = "already_target"
|
||
// StopResumeRecordSkipped 跳过(未到单卡最小重试间隔)。
|
||
StopResumeRecordSkipped = "skipped"
|
||
)
|
||
|
||
const (
|
||
// RateLimitGroupStatusDisabled 限流组停用。
|
||
RateLimitGroupStatusDisabled = 0
|
||
// RateLimitGroupStatusEnabled 限流组启用。
|
||
RateLimitGroupStatusEnabled = 1
|
||
// GatewayRateLimitWindow 限流滑动窗口长度。
|
||
GatewayRateLimitWindow = time.Second
|
||
// GatewayRateLimitConfigTTL 限流组与模式在进程内缓存的时长,超过即重新读取,保证后台修改数秒内生效。
|
||
GatewayRateLimitConfigTTL = 5 * time.Second
|
||
// GatewayCardLastErrorTTL 卡最近一次网关错误保留时长。
|
||
GatewayCardLastErrorTTL = 30 * 24 * time.Hour
|
||
// GatewayCallStatTTL 分钟计数保留时长(覆盖只统计模式一周的评估需要)。
|
||
GatewayCallStatTTL = 8 * 24 * time.Hour
|
||
// GatewayCardCarrierCacheTTL ICCID 到运营商账户映射的缓存时长。
|
||
GatewayCardCarrierCacheTTL = 10 * time.Minute
|
||
// GatewayProviderMessageMaxLen 上游信息落库或展示的最大长度(按字符)。
|
||
GatewayProviderMessageMaxLen = 200
|
||
// StopResumeRecordQueryMaxDays 停复机记录列表单次查询的最大时间跨度(天)。
|
||
StopResumeRecordQueryMaxDays = 31
|
||
)
|
||
|
||
// RedisGatewayQPSKey 返回账户限流组的滑动窗口 Key;carrierID 为 0 表示无法解析账户的卡(单独计量)。
|
||
func RedisGatewayQPSKey(carrierID uint, groupCode string) string {
|
||
return fmt.Sprintf("gateway:qps:%d:%s", carrierID, groupCode)
|
||
}
|
||
|
||
// RedisGatewayGlobalQPSKey 返回全局限流组的滑动窗口 Key。
|
||
func RedisGatewayGlobalQPSKey(groupCode string) string {
|
||
return fmt.Sprintf("gateway:qps:global:%s", groupCode)
|
||
}
|
||
|
||
// RedisGatewayQPSHighWaitingKey 返回限流组正在等待名额的高优先级请求数 Key。
|
||
func RedisGatewayQPSHighWaitingKey(carrierID uint, groupCode string) string {
|
||
return RedisGatewayQPSKey(carrierID, groupCode) + ":high_waiting"
|
||
}
|
||
|
||
// RedisGatewayCallStatKey 返回网关调用分钟计数 Key(Hash:结果类别 → 次数、耗时分桶)。
|
||
func RedisGatewayCallStatKey(carrierID uint, op, minute string) string {
|
||
return fmt.Sprintf("gateway:stat:%d:%s:%s", carrierID, op, minute)
|
||
}
|
||
|
||
// RedisGatewayCardCarrierKey 返回 ICCID 到运营商账户 ID 映射的缓存 Key。
|
||
func RedisGatewayCardCarrierKey(iccid string) string {
|
||
return fmt.Sprintf("gateway:card_carrier:%s", iccid)
|
||
}
|
||
|
||
// RedisGatewayRateLimitGroupsKey 返回限流组配置缓存 Key。
|
||
func RedisGatewayRateLimitGroupsKey() string {
|
||
return "gateway:rate_limit_groups"
|
||
}
|
||
|
||
// RedisGatewayErrorClassificationKey 返回错误分类规则缓存 Key。
|
||
func RedisGatewayErrorClassificationKey() string {
|
||
return "gateway:error_classification"
|
||
}
|
||
|
||
// RedisRateLimitDeferStartKey 返回任务首次被限流时间的 Key,用于累计推迟告警。
|
||
func RedisRateLimitDeferStartKey(taskKey string) string {
|
||
return fmt.Sprintf("gateway:rate_limit_defer:%s", taskKey)
|
||
}
|
||
|
||
// RedisGatewayCardLastErrorKey 返回卡某网关操作最近一次错误的 Key(Hash:类别、码、信息、时间)。
|
||
func RedisGatewayCardLastErrorKey(iccid, op string) string {
|
||
return fmt.Sprintf("gateway:last_error:%s:%s", iccid, op)
|
||
}
|