docs: add research findings

This commit is contained in:
2026-03-27 19:04:17 +08:00
parent cf59380784
commit 3078bc71c8
5 changed files with 1456 additions and 0 deletions

353
.planning/research/STACK.md Normal file
View File

@@ -0,0 +1,353 @@
# 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.02026-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** | 全功能 ORMcode-firstActiveRecord 风格 | ✅ **最适合** |
| sqlc | 编译时类型安全,从 SQL 生成 Go 代码 | ❌ 需要从头重写所有查询 |
| sqlx | SQL 轻量封装,接近原生 database/sql | ❌ 需要全部改写,收益有限 |
| ent | 图模型 ORMcompile-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.02026-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.02026-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**继续使用**
**sonicbytedance/sonic** 在 2025 年基准测试中仍是 Go 生态最快的 JSON 库:
| 库 | 相对速度 | 适用场景 |
|----|---------|---------|
| **sonic** | ~3-4x 快于 std | 高并发 API大 payload如 Excel 导入响应) |
| encoding/json v2Go 1.25 内置) | ~1.8x 快于 std | 标准库,无需引入依赖 |
| encoding/jsonstd | 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纯整数分/厘)存储,避免所有浮点运算
- 适合固定金额计算
- 本项目钱包余额已是此做法 ✅
选项 Bshopspring/decimal用于百分比/比例计算)
- 适合佣金比例计算、退款按比例扣减
- 7000+ GitHub stars已是 Go 社区财务计算标准库
选项 Cgo-moneyRhymond/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 年可观测性实践)
---
### 缺口 4IoT 领域特有):运营商网关客户端 — 无通用标准库
**问题描述:**
本项目有 `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
# 引入 decimalP0 佣金精度修复时)
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*