354 lines
14 KiB
Markdown
354 lines
14 KiB
Markdown
# Stack Research
|
||
|
||
**Domain:** IoT 卡管理平台 — SIM 卡全生命周期 + 代理分销 + 分佣结算
|
||
**Researched:** 2026-03-27
|
||
**Confidence:** MEDIUM-HIGH(核心技术栈 HIGH,外围选项 MEDIUM)
|
||
|
||
---
|
||
|
||
## 结论先行:当前技术栈评估
|
||
|
||
**整体结论:当前技术选型对于该领域是合理的,无需大规模替换。**
|
||
存在 3 个明确的技术债和 1 个值得关注的升级时机。
|
||
|
||
| 组件 | 当前版本 | 最新版本 | 状态 | 建议 |
|
||
|------|---------|---------|------|------|
|
||
| Fiber | v2.52.9 | **v3.1.0** | ⚠️ 大版本落后 | 保持 v2,不升级(见分析) |
|
||
| GORM | v1.31.1 | v1.31.x | ✅ 最新 | 继续使用 |
|
||
| Asynq | v0.25.1 | **v0.26.0** | ⚠️ 落后一个版本 | 可选升级(安全依赖升级) |
|
||
| go-redis | v9.7.0 | v9.18.0 | ⚠️ 落后较多 | 建议升级(无 API 破坏性变更) |
|
||
| sonic | v1.14.2 | v1.14.x | ✅ 近期版本 | 继续使用 |
|
||
| PowerWeChat | v3.4.38 | v3.4.38 | ✅ 最新 | 继续使用 |
|
||
| Go runtime | 1.25.x | 1.25.x | ✅ 最新 | 继续使用 |
|
||
|
||
---
|
||
|
||
## 核心技术栈
|
||
|
||
### 一、HTTP 框架 — Fiber v2(**继续坚守**)
|
||
|
||
| 项目 | 内容 |
|
||
|------|------|
|
||
| 当前版本 | v2.52.9(已是 v2.x 最新) |
|
||
| 最新大版本 | v3.1.0(2026-02-02 正式发布) |
|
||
| **不升级的原因** | v3 有重大破坏性变更,迁移成本高,且本项目有大量存量代码 |
|
||
|
||
**v3 核心破坏性变更(对本项目影响分析):**
|
||
|
||
1. **`c.UserContext()` 被移除** → `Ctx` 本身现在实现 `context.Context`,直接传 `c` 即可。
|
||
- **影响:**本项目全代码库大量使用 `c.UserContext()` 传递用户 Context 到 Service/Store 层,这是最大的迁移成本。
|
||
- **估算:**全局搜索 `UserContext()` 调用点,预估 100+ 处改动。
|
||
|
||
2. **`c.BodyParser()` 移除** → 改用 `c.Bind().Body()`
|
||
- **影响:**所有 Handler 层的请求解析代码需要改写。
|
||
|
||
3. **路由注册 `Add` 方法签名变更** → 影响 `internal/routes/registry.go` 的统一注册逻辑。
|
||
|
||
4. **`app.Mount()` 移除** → 使用 `app.Use()`。
|
||
|
||
**置信度:HIGH**(官方文档 https://docs.gofiber.io/whats_new/ 已确认)
|
||
|
||
**建议:** 保持 v2.52.x,待 v2 EOL 公告或下一个重大重构机会再考虑升级。v2 安全维护至少到 2026 年底,风险可控。
|
||
|
||
---
|
||
|
||
### 二、ORM — GORM v2(**继续使用,无更好替代方案**)
|
||
|
||
**2026 年 Go ORM 格局:**
|
||
|
||
| ORM | 定位 | 适合本项目 |
|
||
|-----|------|-----------|
|
||
| **GORM** | 全功能 ORM,code-first,ActiveRecord 风格 | ✅ **最适合** |
|
||
| sqlc | 编译时类型安全,从 SQL 生成 Go 代码 | ❌ 需要从头重写所有查询 |
|
||
| sqlx | SQL 轻量封装,接近原生 database/sql | ❌ 需要全部改写,收益有限 |
|
||
| ent | 图模型 ORM,compile-time type safety | ❌ 学习成本高,编译慢,不适合现有代码库 |
|
||
|
||
**为什么 GORM 对本项目是正确选择:**
|
||
- CRUD 密集型应用(卡管理、套餐管理、订单、佣金),GORM 的约定优于配置大幅减少样板代码
|
||
- 软删除、钩子(Hooks)、事务等特性本项目大量依赖
|
||
- 当前 v1.31.x 已是最新,无需升级
|
||
|
||
**GORM 的已知性能问题(针对本项目的建议):**
|
||
- 多级代理佣金树查询(最深 7 层)不应使用 GORM `Preload`,而应使用原生 `WITH RECURSIVE` CTE
|
||
- 批量导入(ICCID Excel)应使用 `db.CreateInBatches()` 而非逐行 `Create()`
|
||
|
||
**置信度:HIGH**(多个 2026 年对比文章,主流观点一致)
|
||
|
||
---
|
||
|
||
### 三、任务队列 — Asynq(**继续使用,考虑升级到 v0.26.0**)
|
||
|
||
**最新版本:** v0.26.0(2026-02-03 发布)
|
||
|
||
| 版本 | 关键变更 |
|
||
|------|---------|
|
||
| v0.25.1(当前) | 安全依赖升级 + 增加 `RedisUniversalClient` 支持 |
|
||
| **v0.26.0** | 增加 Task Headers 支持(PR #1070)+ TLS 选项 + 最低 Go 版本升至 1.24 |
|
||
|
||
**为什么不替换 Asynq:**
|
||
在 IoT 卡管理场景中,Asynq 的优势:
|
||
- 基于 Redis(与现有基础设施共享,无额外运维成本)
|
||
- 内置定时任务调度(Scheduler)适合轮询任务场景
|
||
- 任务可视化(Asynqmon Web UI)在生产调试中有价值
|
||
- 竞品(Machinery、Watermill)依赖更重,对单节点场景没有额外收益
|
||
|
||
**建议:** 升级到 v0.26.0(`go get github.com/hibiken/asynq@v0.26.0`),主要收益是上游安全依赖修复,API 完全兼容。
|
||
|
||
**置信度:HIGH**(GitHub Releases 直接验证)
|
||
|
||
---
|
||
|
||
### 四、Redis 客户端 — go-redis v9(**建议升级**)
|
||
|
||
**当前版本:** v9.7.0
|
||
**最新版本:** v9.18.0(2026-02-16)
|
||
|
||
v9.7.0 → v9.18.0 跨越 11 个 patch 版本,均为向后兼容。建议升级原因:
|
||
- 包含若干 bug 修复和性能改进
|
||
- 升级命令:`go get github.com/redis/go-redis/v9@v9.18.0`
|
||
|
||
**置信度:MEDIUM**(pkg.go.dev 直接确认版本)
|
||
|
||
---
|
||
|
||
### 五、JSON 序列化 — sonic(**继续使用**)
|
||
|
||
**sonic(bytedance/sonic)** 在 2025 年基准测试中仍是 Go 生态最快的 JSON 库:
|
||
|
||
| 库 | 相对速度 | 适用场景 |
|
||
|----|---------|---------|
|
||
| **sonic** | ~3-4x 快于 std | 高并发 API,大 payload(如 Excel 导入响应) |
|
||
| encoding/json v2(Go 1.25 内置) | ~1.8x 快于 std | 标准库,无需引入依赖 |
|
||
| encoding/json(std) | 1x 基线 | 无额外依赖场景 |
|
||
|
||
**注意:** Go 1.25 引入了 `encoding/json/v2`,性能约为 sonic 的 50%,但消除了历史行为不一致问题。对于本项目,sonic 仍是正确选择:本项目已集成且使用 Fiber 的 sonic 替换,迁移收益不大。
|
||
|
||
**置信度:HIGH**(2025-09 Reddit benchmark + Trendyol 生产迁移案例)
|
||
|
||
---
|
||
|
||
## 领域特有技术栈缺口分析
|
||
|
||
### 缺口 1:金融精度问题 ⚠️(**重大技术债**)
|
||
|
||
**问题描述:**
|
||
IoT 卡管理平台涉及两类精度敏感计算:
|
||
1. **货币金额**:钱包余额、佣金金额(差价佣金、一次性佣金)、套餐价格
|
||
2. **流量计费**:MB/GB 流量用量计算、按比例退款
|
||
|
||
**当前实现风险:**
|
||
- 余额字段使用 `int64`(存储"分")—— **钱包余额做法正确**
|
||
- 但佣金链计算(差价 = 上层价格 - 下层成本)中,如果涉及百分比分佣(如"提成 15%"),用 `float64` 计算后再转 `int64` 会有精度损失
|
||
|
||
**标准做法(2025 年行业共识):**
|
||
|
||
```
|
||
选项 A:纯整数(分/厘)存储,避免所有浮点运算
|
||
- 适合固定金额计算
|
||
- 本项目钱包余额已是此做法 ✅
|
||
|
||
选项 B:shopspring/decimal(用于百分比/比例计算)
|
||
- 适合佣金比例计算、退款按比例扣减
|
||
- 7000+ GitHub stars,已是 Go 社区财务计算标准库
|
||
|
||
选项 C:go-money(Rhymond/go-money)
|
||
- 适合多币种场景,本项目不需要
|
||
```
|
||
|
||
**建议:**
|
||
引入 `github.com/shopspring/decimal` v1.4.0,**仅用于**:
|
||
- 佣金比例计算(如方案 I-3:退款按比例扣减代理佣金)
|
||
- 流量按比例计费(方案 E 的流量体系改革)
|
||
|
||
不需要全局替换 int64 余额字段,仅在需要乘除法的计算环节使用 decimal,最终结果转 int64 存储。
|
||
|
||
**置信度:HIGH**(Modern Treasury 官方博客 2025-08 + shopspring/decimal 7286 stars)
|
||
|
||
---
|
||
|
||
### 缺口 2:多级代理查询性能 ⚠️(**架构风险**)
|
||
|
||
**问题描述:**
|
||
本项目代理层级最多 7 层,`GetSubordinateShopIDs()` 使用 PostgreSQL `WITH RECURSIVE` CTE 查询,结果缓存 30 分钟。这个架构是正确的。
|
||
|
||
**潜在风险:**
|
||
- 佣金链计算时,N 层递归分佣可能退化为 N 次单独 DB 查询(N+1 问题)
|
||
- 7 层 × 每层查询 = 最坏 7 次 DB 往返,而 DB 查询要求 < 50ms
|
||
|
||
**2025 年标准方案:**
|
||
对于多级分佣树计算,行业标准是一次性将整条链路数据加载到内存,而非逐层查询:
|
||
|
||
```sql
|
||
-- 一次性获取完整佣金链(从叶子节点到根节点)
|
||
WITH RECURSIVE commission_chain AS (
|
||
SELECT shop_id, parent_id, level, 0 AS depth
|
||
FROM tb_shop WHERE id = $1
|
||
UNION ALL
|
||
SELECT s.shop_id, s.parent_id, s.level, cc.depth + 1
|
||
FROM tb_shop s
|
||
INNER JOIN commission_chain cc ON s.id = cc.parent_id
|
||
)
|
||
SELECT * FROM commission_chain ORDER BY depth;
|
||
```
|
||
|
||
当前代码已经有 `WITH RECURSIVE` 基础,但需要确认佣金计算是否利用了这个能力。
|
||
|
||
**置信度:MEDIUM**(基于代码库 PROJECT.md 分析 + PostgreSQL 官方文档)
|
||
|
||
---
|
||
|
||
### 缺口 3:可观测性 ⚠️(**生产上线前需解决**)
|
||
|
||
**问题描述:**
|
||
当前技术栈的可观测性仅有:
|
||
- 应用日志(Zap)
|
||
- 访问日志
|
||
- Asynq 任务状态(via Asynqmon 可选)
|
||
- 健康检查 `GET /health`
|
||
|
||
**缺失:**
|
||
- 没有指标(Metrics)收集
|
||
- 没有链路追踪(Tracing)
|
||
- 没有告警(Alerting)
|
||
|
||
**对于当前阶段(MVP 修复上线):** 可以暂时接受,PROJECT.md 的 Out of Scope 已明确 "P2-6 告警通知渠道 — 无关紧要,暂不做"。
|
||
|
||
**但如果平台上线后扩展:**
|
||
- 轻量级方案:Prometheus + Grafana(已是 Go 社区标准)
|
||
- 零侵入方案:OpenTelemetry Go SDK(标准化,支持后续接入任意后端)
|
||
|
||
**置信度:MEDIUM**(基于 Go 社区 2025 年可观测性实践)
|
||
|
||
---
|
||
|
||
### 缺口 4(IoT 领域特有):运营商网关客户端 — 无通用标准库
|
||
|
||
**问题描述:**
|
||
本项目有 `internal/gateway/client.go`(外部 Gateway 服务 HTTP 客户端)。IoT SIM 卡管理平台通常需要对接:
|
||
- GSMA M2M 标准(SM-DP+/SM-DS for eSIM)
|
||
- 运营商私有 API(中国联通、移动、电信)
|
||
|
||
**2025 年实际情况:**
|
||
国内运营商 IoT 平台(移动 OneNET、电信 CTWing、联通 Open)均为私有 REST/SOAP API,**没有标准化的 Go SDK**。
|
||
|
||
当前项目自研 `internal/gateway/client.go` 是唯一可行路径,符合行业惯例。
|
||
|
||
**置信度:HIGH**(行业调研确认,无通用 Go SDK 存在)
|
||
|
||
---
|
||
|
||
## 当前栈中已弃用/有问题的依赖
|
||
|
||
| 依赖 | 问题 | 建议 |
|
||
|------|------|------|
|
||
| `aws/aws-sdk-go` (v1) | AWS SDK Go v1 已于 2025-07-31 进入 Maintenance Mode,不再接收功能更新 | 低优先级,当前对接联通云 OSS,可继续使用;如有大范围重构可迁移到 `aws/aws-sdk-go-v2` |
|
||
| `excelize/v2` | 无严重问题,版本跟进即可 | — |
|
||
|
||
**AWS SDK v1 注意:** 仅 Maintenance Mode,不是 End of Life,安全补丁仍会发布。迁移到 v2 需要较大代码改动,不建议在当前 MVP 阶段操作。
|
||
|
||
**置信度:MEDIUM**(AWS 官方公告,2025-07-31)
|
||
|
||
---
|
||
|
||
## 可选补充库
|
||
|
||
以下库不在当前技术栈中,但对特定需求有价值:
|
||
|
||
| 库 | 版本 | 用途 | 引入时机 |
|
||
|----|------|------|---------|
|
||
| `shopspring/decimal` | v1.4.0 | 佣金比例计算、退款按比例计算 | **方案 I(退款)实现时** |
|
||
| `golang-migrate/migrate` | v4.18.x | 数据库迁移(已在项目使用) | — 已用 |
|
||
| `hibiken/asynqmon` | latest | Asynq 任务可视化 Web UI | 生产环境调试时 |
|
||
|
||
---
|
||
|
||
## 替代方案对比
|
||
|
||
| 类别 | 当前选择 | 备选 | 不替换的理由 |
|
||
|------|---------|------|------------|
|
||
| HTTP 框架 | Fiber v2 | Gin, Echo, Chi, Fiber v3 | 大量存量代码;v3 破坏性变更成本高 |
|
||
| ORM | GORM | sqlc, sqlx, ent | 项目已深度集成,CRUD 场景 GORM 是最优解 |
|
||
| 任务队列 | Asynq | Machinery, Watermill, Temporal | Redis 复用优势;Temporal 对单节点过重 |
|
||
| 消息队列 | 无(Asynq 兼任) | NATS, Kafka | 当前规模不需要独立 MQ |
|
||
| 缓存 | Redis | Memcached | Redis 功能更丰富,已是基础设施 |
|
||
| 数据库 | PostgreSQL | MySQL, CockroachDB | PostgreSQL 的递归 CTE 对层级数据有优势 |
|
||
| JSON | sonic | encoding/json, json/v2 | sonic 性能优势在高并发场景显著 |
|
||
|
||
---
|
||
|
||
## 版本兼容性注意事项
|
||
|
||
| 依赖组合 | 状态 | 注意 |
|
||
|---------|------|------|
|
||
| Fiber v2 + Go 1.25 | ✅ 兼容 | Fiber v2.52.9 已适配 Go 1.25 |
|
||
| Fiber v3 + Go 1.25 | ⚠️ 要求 Go 1.25+ | v3 以 Go 1.25 为最低版本 |
|
||
| Asynq v0.26.0 + Go 1.25 | ✅ 兼容 | v0.26.0 要求 Go 1.24+,1.25 满足 |
|
||
| GORM v1.31.1 + PostgreSQL 14+ | ✅ 兼容 | — |
|
||
| PowerWeChat v3.4.38 + Go 1.25 | ✅ 兼容 | 官方声明 Go 1.23+ |
|
||
|
||
---
|
||
|
||
## 关键技术债总结(优先级排序)
|
||
|
||
### P0:必须在上线前解决
|
||
|
||
**金融精度风险**(佣金计算)
|
||
- 检查所有涉及百分比/比例的佣金计算代码,确认没有 `float64` 中间步骤
|
||
- 方案 I(退款按比例扣减佣金)实现时必须引入 `shopspring/decimal`
|
||
|
||
### P1:上线后尽快处理
|
||
|
||
**go-redis 版本落后**
|
||
- 从 v9.7.0 升级到 v9.18.0,无 API 破坏性变更,安全隐患修复
|
||
|
||
**Asynq 版本落后**
|
||
- 从 v0.25.1 升级到 v0.26.0,获得安全修复
|
||
|
||
### P2:中期规划
|
||
|
||
**AWS SDK v1 → v2 迁移**(对象存储)
|
||
- 不紧急,v1 仍有安全支持,规划下一个重大重构时处理
|
||
|
||
**Fiber v2 → v3 迁移评估**
|
||
- v2 仍在维护,不需要立即升级
|
||
- 建议在明年底(2027)重新评估是否升级
|
||
|
||
---
|
||
|
||
## 安装/升级命令参考
|
||
|
||
```bash
|
||
# 升级 Asynq(推荐)
|
||
go get github.com/hibiken/asynq@v0.26.0
|
||
|
||
# 升级 go-redis(推荐)
|
||
go get github.com/redis/go-redis/v9@v9.18.0
|
||
|
||
# 引入 decimal(P0 佣金精度修复时)
|
||
go get github.com/shopspring/decimal@v1.4.0
|
||
|
||
# 升级所有兼容依赖(谨慎,逐一验证)
|
||
go get -u ./...
|
||
```
|
||
|
||
---
|
||
|
||
## Sources
|
||
|
||
| 来源 | 内容 | 置信度 |
|
||
|------|------|--------|
|
||
| https://docs.gofiber.io/whats_new/ | Fiber v3 破坏性变更完整列表 | HIGH |
|
||
| https://newreleases.io/project/github/hibiken/asynq/release/v0.26.0 | Asynq v0.26.0 发布说明 | HIGH |
|
||
| https://pkg.go.dev/github.com/redis/go-redis/v9 | go-redis 最新版本 v9.18.0 | HIGH |
|
||
| https://reintech.io/blog/sqlc-vs-gorm-vs-sqlx-go-database-libraries-compared-2026 | GORM vs sqlc vs sqlx 2026 深度对比 | MEDIUM |
|
||
| https://encore.cloud/resources/go-orms | Go ORM 2026 对比(GORM/sqlc/ent)| MEDIUM |
|
||
| https://pkg.go.dev/github.com/shopspring/decimal@v1.4.0 | shopspring/decimal v1.4.0 | HIGH |
|
||
| https://www.moderntreasury.com/journal/floats-dont-work-for-storing-cents | 金融精度使用整数的行业实践 | HIGH |
|
||
| Reddit r/golang 2025-09 JSON benchmark | sonic vs std vs json/v2 基准 | MEDIUM |
|
||
| https://pkg.go.dev/github.com/ArtisanCloud/PowerWeChat/v3@v3.4.38 | PowerWeChat 最新版本确认 | HIGH |
|
||
|
||
---
|
||
|
||
*Stack research for: IoT SIM 卡管理平台(Go + Fiber + GORM + Asynq + PostgreSQL + Redis)*
|
||
*Researched: 2026-03-27*
|