feat: 实现 IoT 卡轮询系统(支持千万级卡规模)
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m35s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m35s
实现功能: - 实名状态检查轮询(可配置间隔) - 卡流量检查轮询(支持跨月流量追踪) - 套餐检查与超额自动停机 - 分布式并发控制(Redis 信号量) - 手动触发轮询(单卡/批量/条件筛选) - 数据清理配置与执行 - 告警规则与历史记录 - 实时监控统计(队列/性能/并发) 性能优化: - Redis 缓存卡信息,减少 DB 查询 - Pipeline 批量写入 Redis - 异步流量记录写入 - 渐进式初始化(10万卡/批) 压测工具(scripts/benchmark/): - Mock Gateway 模拟上游服务 - 测试卡生成器 - 配置初始化脚本 - 实时监控脚本 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,29 +1,152 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// PollingConfig 轮询配置模型
|
||||
// 支持梯度轮询策略(实名检查、卡流量检查、套餐流量检查)
|
||||
// PollingConfig 轮询配置表
|
||||
type PollingConfig struct {
|
||||
gorm.Model
|
||||
BaseModel `gorm:"embedded"`
|
||||
ConfigName string `gorm:"column:config_name;type:varchar(100);uniqueIndex:idx_polling_config_name,where:deleted_at IS NULL;not null;comment:配置名称(如 未实名卡、实名卡)" json:"config_name"`
|
||||
Description string `gorm:"column:description;type:varchar(500);comment:配置描述" json:"description"`
|
||||
CardCondition string `gorm:"column:card_condition;type:varchar(50);comment:卡状态条件 not_real_name-未实名 real_name-已实名 activated-已激活 suspended-已停用" json:"card_condition"`
|
||||
CarrierID uint `gorm:"column:carrier_id;index;comment:运营商ID(NULL表示所有运营商)" json:"carrier_id"`
|
||||
RealNameCheckEnabled bool `gorm:"column:real_name_check_enabled;type:boolean;default:false;comment:是否启用实名检查" json:"real_name_check_enabled"`
|
||||
RealNameCheckInterval int `gorm:"column:real_name_check_interval;type:int;default:60;comment:实名检查间隔(秒)" json:"real_name_check_interval"`
|
||||
CardDataCheckEnabled bool `gorm:"column:card_data_check_enabled;type:boolean;default:false;comment:是否启用卡流量检查" json:"card_data_check_enabled"`
|
||||
CardDataCheckInterval int `gorm:"column:card_data_check_interval;type:int;default:60;comment:卡流量检查间隔(秒)" json:"card_data_check_interval"`
|
||||
PackageCheckEnabled bool `gorm:"column:package_check_enabled;type:boolean;default:false;comment:是否启用套餐流量检查" json:"package_check_enabled"`
|
||||
PackageCheckInterval int `gorm:"column:package_check_interval;type:int;default:60;comment:套餐流量检查间隔(秒)" json:"package_check_interval"`
|
||||
Priority int `gorm:"column:priority;type:int;default:100;not null;comment:优先级(数字越小优先级越高)" json:"priority"`
|
||||
Status int `gorm:"column:status;type:int;default:1;not null;comment:状态 1-启用 2-禁用" json:"status"`
|
||||
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
||||
ConfigName string `gorm:"column:config_name;type:varchar(100);not null;comment:配置名称" json:"config_name"`
|
||||
CardCondition string `gorm:"column:card_condition;type:varchar(50);comment:卡状态条件:not_real_name/real_name/activated/suspended" json:"card_condition"`
|
||||
CardCategory string `gorm:"column:card_category;type:varchar(50);comment:卡业务类型:normal/industry" json:"card_category"`
|
||||
CarrierID *uint `gorm:"column:carrier_id;comment:运营商ID(可选,精确匹配)" json:"carrier_id"`
|
||||
Priority int `gorm:"column:priority;not null;default:100;comment:优先级(数字越小优先级越高)" json:"priority"`
|
||||
RealnameCheckInterval *int `gorm:"column:realname_check_interval;comment:实名检查间隔(秒),NULL表示不检查" json:"realname_check_interval"`
|
||||
CarddataCheckInterval *int `gorm:"column:carddata_check_interval;comment:流量检查间隔(秒),NULL表示不检查" json:"carddata_check_interval"`
|
||||
PackageCheckInterval *int `gorm:"column:package_check_interval;comment:套餐检查间隔(秒),NULL表示不检查" json:"package_check_interval"`
|
||||
Status int16 `gorm:"column:status;type:smallint;not null;default:1;comment:状态:0-禁用,1-启用" json:"status"`
|
||||
Description string `gorm:"column:description;type:text;comment:配置说明" json:"description"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"`
|
||||
CreatedBy *uint `gorm:"column:created_by;comment:创建人ID" json:"created_by"`
|
||||
UpdatedBy *uint `gorm:"column:updated_by;comment:更新人ID" json:"updated_by"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (PollingConfig) TableName() string {
|
||||
return "tb_polling_config"
|
||||
}
|
||||
|
||||
// PollingConcurrencyConfig 并发控制配置表
|
||||
type PollingConcurrencyConfig struct {
|
||||
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
||||
TaskType string `gorm:"column:task_type;type:varchar(50);uniqueIndex;not null;comment:任务类型:realname/carddata/package/stop_start" json:"task_type"`
|
||||
MaxConcurrency int `gorm:"column:max_concurrency;not null;default:50;comment:最大并发数" json:"max_concurrency"`
|
||||
Description string `gorm:"column:description;type:text;comment:配置说明" json:"description"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"`
|
||||
UpdatedBy *uint `gorm:"column:updated_by;comment:更新人ID" json:"updated_by"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (PollingConcurrencyConfig) TableName() string {
|
||||
return "tb_polling_concurrency_config"
|
||||
}
|
||||
|
||||
// PollingAlertRule 告警规则表
|
||||
type PollingAlertRule struct {
|
||||
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
||||
RuleName string `gorm:"column:rule_name;type:varchar(100);not null;comment:规则名称" json:"rule_name"`
|
||||
TaskType string `gorm:"column:task_type;type:varchar(50);not null;comment:任务类型:realname/carddata/package" json:"task_type"`
|
||||
MetricType string `gorm:"column:metric_type;type:varchar(50);not null;comment:指标类型:queue_size/success_rate/avg_duration/concurrency" json:"metric_type"`
|
||||
Operator string `gorm:"column:operator;type:varchar(20);not null;comment:比较运算符:gt/lt/gte/lte/eq" json:"operator"`
|
||||
Threshold float64 `gorm:"column:threshold;type:decimal(10,2);not null;comment:阈值" json:"threshold"`
|
||||
DurationMinutes int `gorm:"column:duration_minutes;not null;default:5;comment:持续时长(分钟),避免短暂波动" json:"duration_minutes"`
|
||||
AlertLevel string `gorm:"column:alert_level;type:varchar(20);not null;default:'warning';comment:告警级别:info/warning/error/critical" json:"alert_level"`
|
||||
NotificationChannels string `gorm:"column:notification_channels;type:text;comment:通知渠道(JSON数组):[\"email\",\"sms\",\"webhook\"]" json:"notification_channels"`
|
||||
NotificationConfig string `gorm:"column:notification_config;type:text;comment:通知配置(JSON)" json:"notification_config"`
|
||||
Status int16 `gorm:"column:status;type:smallint;not null;default:1;comment:状态:0-禁用,1-启用" json:"status"`
|
||||
CooldownMinutes int `gorm:"column:cooldown_minutes;not null;default:5;comment:冷却期(分钟),避免重复告警" json:"cooldown_minutes"`
|
||||
Description string `gorm:"column:description;type:text;comment:规则说明" json:"description"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"`
|
||||
CreatedBy *uint `gorm:"column:created_by;comment:创建人ID" json:"created_by"`
|
||||
UpdatedBy *uint `gorm:"column:updated_by;comment:更新人ID" json:"updated_by"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (PollingAlertRule) TableName() string {
|
||||
return "tb_polling_alert_rule"
|
||||
}
|
||||
|
||||
// PollingAlertHistory 告警历史表
|
||||
type PollingAlertHistory struct {
|
||||
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
||||
RuleID uint `gorm:"column:rule_id;not null;comment:告警规则ID" json:"rule_id"`
|
||||
TaskType string `gorm:"column:task_type;type:varchar(50);not null;comment:任务类型" json:"task_type"`
|
||||
MetricType string `gorm:"column:metric_type;type:varchar(50);not null;comment:指标类型" json:"metric_type"`
|
||||
AlertLevel string `gorm:"column:alert_level;type:varchar(20);not null;comment:告警级别" json:"alert_level"`
|
||||
CurrentValue float64 `gorm:"column:current_value;type:decimal(10,2);not null;comment:当前值" json:"current_value"`
|
||||
Threshold float64 `gorm:"column:threshold;type:decimal(10,2);not null;comment:阈值" json:"threshold"`
|
||||
AlertMessage string `gorm:"column:alert_message;type:text;not null;comment:告警消息" json:"alert_message"`
|
||||
NotificationChannels string `gorm:"column:notification_channels;type:text;comment:通知渠道(JSON数组)" json:"notification_channels"`
|
||||
NotificationStatus string `gorm:"column:notification_status;type:varchar(20);comment:通知状态:pending/sent/failed" json:"notification_status"`
|
||||
NotificationResult string `gorm:"column:notification_result;type:text;comment:通知结果(JSON)" json:"notification_result"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:告警时间" json:"created_at"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (PollingAlertHistory) TableName() string {
|
||||
return "tb_polling_alert_history"
|
||||
}
|
||||
|
||||
// DataCleanupConfig 数据清理配置表
|
||||
type DataCleanupConfig struct {
|
||||
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
||||
TargetTable string `gorm:"column:table_name;type:varchar(100);uniqueIndex;not null;comment:表名" json:"table_name"`
|
||||
RetentionDays int `gorm:"column:retention_days;not null;comment:保留天数" json:"retention_days"`
|
||||
Enabled int16 `gorm:"column:enabled;type:smallint;not null;default:1;comment:是否启用:0-禁用,1-启用" json:"enabled"`
|
||||
BatchSize int `gorm:"column:batch_size;not null;default:10000;comment:每批删除条数" json:"batch_size"`
|
||||
Description string `gorm:"column:description;type:text;comment:配置说明" json:"description"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"`
|
||||
UpdatedBy *uint `gorm:"column:updated_by;comment:更新人ID" json:"updated_by"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (DataCleanupConfig) TableName() string {
|
||||
return "tb_data_cleanup_config"
|
||||
}
|
||||
|
||||
// DataCleanupLog 数据清理日志表
|
||||
type DataCleanupLog struct {
|
||||
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
||||
TargetTable string `gorm:"column:table_name;type:varchar(100);not null;comment:表名" json:"table_name"`
|
||||
CleanupType string `gorm:"column:cleanup_type;type:varchar(50);not null;comment:清理类型:scheduled/manual" json:"cleanup_type"`
|
||||
RetentionDays int `gorm:"column:retention_days;not null;comment:保留天数" json:"retention_days"`
|
||||
DeletedCount int64 `gorm:"column:deleted_count;not null;default:0;comment:删除记录数" json:"deleted_count"`
|
||||
DurationMs int64 `gorm:"column:duration_ms;not null;default:0;comment:执行耗时(毫秒)" json:"duration_ms"`
|
||||
Status string `gorm:"column:status;type:varchar(20);not null;comment:状态:success/failed/running" json:"status"`
|
||||
ErrorMessage string `gorm:"column:error_message;type:text;comment:错误信息" json:"error_message"`
|
||||
StartedAt time.Time `gorm:"column:started_at;not null;comment:开始时间" json:"started_at"`
|
||||
CompletedAt *time.Time `gorm:"column:completed_at;comment:完成时间" json:"completed_at"`
|
||||
TriggeredBy *uint `gorm:"column:triggered_by;comment:触发人ID(手动触发时)" json:"triggered_by"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (DataCleanupLog) TableName() string {
|
||||
return "tb_data_cleanup_log"
|
||||
}
|
||||
|
||||
// PollingManualTriggerLog 手动触发日志表
|
||||
type PollingManualTriggerLog struct {
|
||||
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
||||
TaskType string `gorm:"column:task_type;type:varchar(50);not null;comment:任务类型:realname/carddata/package" json:"task_type"`
|
||||
TriggerType string `gorm:"column:trigger_type;type:varchar(50);not null;comment:触发类型:single/batch/by_condition" json:"trigger_type"`
|
||||
CardIDs string `gorm:"column:card_ids;type:text;comment:卡ID列表(JSON数组)" json:"card_ids"`
|
||||
ConditionFilter string `gorm:"column:condition_filter;type:text;comment:筛选条件(JSON)" json:"condition_filter"`
|
||||
TotalCount int `gorm:"column:total_count;not null;default:0;comment:总卡数" json:"total_count"`
|
||||
ProcessedCount int `gorm:"column:processed_count;not null;default:0;comment:已处理数" json:"processed_count"`
|
||||
SuccessCount int `gorm:"column:success_count;not null;default:0;comment:成功数" json:"success_count"`
|
||||
FailedCount int `gorm:"column:failed_count;not null;default:0;comment:失败数" json:"failed_count"`
|
||||
Status string `gorm:"column:status;type:varchar(20);not null;comment:状态:pending/processing/completed/cancelled" json:"status"`
|
||||
TriggeredBy uint `gorm:"column:triggered_by;not null;comment:触发人ID" json:"triggered_by"`
|
||||
TriggeredAt time.Time `gorm:"column:triggered_at;not null;default:CURRENT_TIMESTAMP;comment:触发时间" json:"triggered_at"`
|
||||
CompletedAt *time.Time `gorm:"column:completed_at;comment:完成时间" json:"completed_at"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (PollingManualTriggerLog) TableName() string {
|
||||
return "tb_polling_manual_trigger_log"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user