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:
156
scripts/benchmark/init_config.go
Normal file
156
scripts/benchmark/init_config.go
Normal file
@@ -0,0 +1,156 @@
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
// PollingConfig 轮询配置
|
||||
type PollingConfig struct {
|
||||
ID uint `gorm:"primaryKey"`
|
||||
ConfigName string `gorm:"column:config_name"`
|
||||
CardCondition *string `gorm:"column:card_condition"`
|
||||
CardCategory *string `gorm:"column:card_category"`
|
||||
CarrierID *uint `gorm:"column:carrier_id"`
|
||||
Priority int `gorm:"column:priority"`
|
||||
RealnameCheckInterval *int `gorm:"column:realname_check_interval"`
|
||||
CarddataCheckInterval *int `gorm:"column:carddata_check_interval"`
|
||||
PackageCheckInterval *int `gorm:"column:package_check_interval"`
|
||||
Status int `gorm:"column:status;default:1"`
|
||||
Description string `gorm:"column:description"`
|
||||
}
|
||||
|
||||
func (PollingConfig) TableName() string {
|
||||
return "tb_polling_config"
|
||||
}
|
||||
|
||||
// PollingConcurrencyConfig 并发控制配置
|
||||
type PollingConcurrencyConfig struct {
|
||||
ID uint `gorm:"primaryKey"`
|
||||
TaskType string `gorm:"column:task_type"`
|
||||
MaxConcurrency int `gorm:"column:max_concurrency"`
|
||||
Description string `gorm:"column:description"`
|
||||
}
|
||||
|
||||
func (PollingConcurrencyConfig) TableName() string {
|
||||
return "tb_polling_concurrency_config"
|
||||
}
|
||||
|
||||
func ptr[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("=== 初始化轮询配置 ===")
|
||||
|
||||
// 连接数据库
|
||||
dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
|
||||
os.Getenv("JUNHONG_DATABASE_HOST"),
|
||||
os.Getenv("JUNHONG_DATABASE_PORT"),
|
||||
os.Getenv("JUNHONG_DATABASE_USER"),
|
||||
os.Getenv("JUNHONG_DATABASE_PASSWORD"),
|
||||
os.Getenv("JUNHONG_DATABASE_DBNAME"),
|
||||
)
|
||||
|
||||
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Silent),
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("连接数据库失败: %v", err)
|
||||
}
|
||||
fmt.Println("✓ 数据库连接成功")
|
||||
|
||||
// 清空现有配置
|
||||
db.Exec("DELETE FROM tb_polling_config")
|
||||
db.Exec("DELETE FROM tb_polling_concurrency_config")
|
||||
fmt.Println("✓ 清空现有配置")
|
||||
|
||||
// 插入轮询配置
|
||||
configs := []PollingConfig{
|
||||
{
|
||||
ConfigName: "未实名卡轮询",
|
||||
CardCondition: ptr("not_real_name"),
|
||||
Priority: 10,
|
||||
RealnameCheckInterval: ptr(300), // 5分钟
|
||||
Status: 1,
|
||||
Description: "未实名卡每5分钟检查一次实名状态",
|
||||
},
|
||||
{
|
||||
ConfigName: "行业卡轮询",
|
||||
CardCategory: ptr("industry"),
|
||||
Priority: 15,
|
||||
CarddataCheckInterval: ptr(3600), // 1小时
|
||||
PackageCheckInterval: ptr(3600),
|
||||
Status: 1,
|
||||
Description: "行业卡无需实名检查,每小时检查流量和套餐",
|
||||
},
|
||||
{
|
||||
ConfigName: "已实名卡轮询",
|
||||
CardCondition: ptr("real_name"),
|
||||
Priority: 20,
|
||||
RealnameCheckInterval: ptr(86400), // 1天
|
||||
Status: 1,
|
||||
Description: "已实名卡每天检查一次实名状态",
|
||||
},
|
||||
{
|
||||
ConfigName: "已激活卡轮询",
|
||||
CardCondition: ptr("activated"),
|
||||
Priority: 30,
|
||||
CarddataCheckInterval: ptr(3600), // 1小时
|
||||
PackageCheckInterval: ptr(3600),
|
||||
Status: 1,
|
||||
Description: "已激活卡每小时检查流量和套餐",
|
||||
},
|
||||
{
|
||||
ConfigName: "默认轮询配置",
|
||||
Priority: 100,
|
||||
RealnameCheckInterval: ptr(86400),
|
||||
CarddataCheckInterval: ptr(86400),
|
||||
PackageCheckInterval: ptr(86400),
|
||||
Status: 1,
|
||||
Description: "默认配置,每天检查一次",
|
||||
},
|
||||
}
|
||||
|
||||
for _, cfg := range configs {
|
||||
if err := db.Create(&cfg).Error; err != nil {
|
||||
log.Printf("插入配置失败 [%s]: %v", cfg.ConfigName, err)
|
||||
} else {
|
||||
fmt.Printf(" + %s (优先级: %d)\n", cfg.ConfigName, cfg.Priority)
|
||||
}
|
||||
}
|
||||
fmt.Println("✓ 轮询配置初始化完成")
|
||||
|
||||
// 插入并发控制配置(5+ Worker 场景,每种任务 2000-5000 并发)
|
||||
concurrencyConfigs := []PollingConcurrencyConfig{
|
||||
{TaskType: "realname", MaxConcurrency: 5000, Description: "实名检查任务最大并发数"},
|
||||
{TaskType: "carddata", MaxConcurrency: 5000, Description: "流量检查任务最大并发数"},
|
||||
{TaskType: "package", MaxConcurrency: 5000, Description: "套餐检查任务最大并发数"},
|
||||
{TaskType: "stop_start", MaxConcurrency: 5000, Description: "停复机操作最大并发数"},
|
||||
}
|
||||
|
||||
for _, cfg := range concurrencyConfigs {
|
||||
if err := db.Create(&cfg).Error; err != nil {
|
||||
log.Printf("插入并发配置失败 [%s]: %v", cfg.TaskType, err)
|
||||
} else {
|
||||
fmt.Printf(" + %s (最大并发: %d)\n", cfg.TaskType, cfg.MaxConcurrency)
|
||||
}
|
||||
}
|
||||
fmt.Println("✓ 并发控制配置初始化完成")
|
||||
|
||||
// 验证
|
||||
var pollingCount, concurrencyCount int64
|
||||
db.Model(&PollingConfig{}).Count(&pollingCount)
|
||||
db.Model(&PollingConcurrencyConfig{}).Count(&concurrencyCount)
|
||||
fmt.Printf("\n=== 初始化完成 ===\n")
|
||||
fmt.Printf("轮询配置: %d 条\n", pollingCount)
|
||||
fmt.Printf("并发配置: %d 条\n", concurrencyCount)
|
||||
}
|
||||
Reference in New Issue
Block a user