- 移除不必要的配置字段和复杂错误类型 - 简化trace和log初始化逻辑,保留核心功能 - 使用标准Go错误替代自定义错误结构 - 启用默认批处理和消息丢弃机制- 保留gzip压缩和自动重连功能- 更新相关文档路径引用 - 添加OTel简化增强实现说明文档
11 KiB
11 KiB
京东订单创建逻辑重构报告
概述
本次重构针对京东Cookie管理模块的订单创建逻辑,主要完成以下目标:
- 添加重试机制:解决Cookie失效和京东接口调用失败的问题
- 优化文件结构:将庞大的
order.go文件拆分为多个职责明确的文件 - 增强容错能力:提升系统的稳定性和可靠性
重构内容
1. 文件重构
原有文件结构
internal/logic/jd_cookie/
├── account.go # Cookie账户管理
├── history.go # 历史记录管理
├── index.go # 服务注册
├── order.go # 订单管理(700+ 行)
├── order_test.go # 测试文件
└── rotation.go # Cookie轮询
新文件结构
internal/logic/jd_cookie/
├── account.go # Cookie账户管理
├── history.go # 历史记录管理
├── index.go # 服务注册
├── order_create.go # 订单创建逻辑(带重试机制)
├── order_query.go # 订单查询逻辑
├── order_jd.go # 京东订单管理逻辑
├── order_utils.go # 订单工具方法
├── order_test.go # 测试文件
└── rotation.go # Cookie轮询
文件职责划分
| 文件 | 职责 | 核心方法 |
|---|---|---|
order_create.go |
订单创建与重试逻辑 | CreateOrder, createNewJdOrderWithRetry |
order_query.go |
订单查询与列表 | GetOrder, ListOrder, GetPaymentUrl |
order_jd.go |
京东订单管理与检查 | GetJdOrder, ListJdOrder, CheckJdOrderPayment, ExtractCardInfo |
order_utils.go |
通用辅助方法 | 数据库查询、更新、京东接口调用等 |
2. 核心改进
2.1 订单创建重试机制
改进前:
// 旧逻辑:获取Cookie失败或下单失败直接返回错误
cookieId, err := s.GetAvailableCookie(ctx)
if err != nil {
return "", "", "", gerror.Wrap(err, "获取可用Cookie失败")
}
jdOrderId, payId, wxPayUrl, err = s.callJdCreateOrder(ctx, cookieId, amount, category)
if err != nil {
s.handleCookieFailure(ctx, cookieId, orderId)
return "", "", "", gerror.Wrap(err, "京东下单失败")
}
改进后:
// 新逻辑:支持多次重试,自动切换Cookie
func (s *sJdCookie) createNewJdOrderWithRetry(ctx context.Context, orderId string, amount float64, category consts.RedeemOrderCardCategory) (jdOrderId, cookieId, wxPayUrl string, err error) {
const maxRetryCount = 10 // 最大重试次数
var lastErr error
var triedCookies []string // 记录已尝试的Cookie
for retryCount := 0; retryCount < maxRetryCount; retryCount++ {
// 获取可用的Cookie
availableCookieId, cookieErr := s.GetAvailableCookie(ctx)
if cookieErr != nil {
lastErr = cookieErr
break // 没有可用Cookie,停止重试
}
// 检查是否已经尝试过这个Cookie
if s.hasCookieBeenTried(triedCookies, availableCookieId) {
continue
}
// 记录已尝试的Cookie
triedCookies = append(triedCookies, availableCookieId)
// 调用京东下单接口
var payId string
jdOrderId, payId, wxPayUrl, lastErr = s.callJdCreateOrder(ctx, availableCookieId, amount, category)
if lastErr != nil {
// Cookie失败,更新状态
s.handleCookieFailure(ctx, availableCookieId, orderId)
continue // 继续下一次重试
}
// 下单成功,创建京东订单记录
err = s.createJdOrderRecord(ctx, jdOrderId, payId, availableCookieId, category, amount, wxPayUrl)
if err != nil {
return "", "", "", gerror.Wrap(err, "创建京东订单记录失败")
}
// 返回成功结果
return jdOrderId, availableCookieId, wxPayUrl, nil
}
// 所有重试都失败了
if lastErr == nil {
lastErr = gerror.New(consts.ErrCodeCookieNotAvailable)
}
return "", "", "", gerror.Wrapf(lastErr, "创建京东订单失败,已尝试%d个Cookie", len(triedCookies))
}
重试机制的优势:
- 自动容错:单个Cookie失败不会导致整个订单创建失败
- Cookie轮换:自动切换到下一个可用Cookie
- 避免重复:记录已尝试的Cookie,避免重复尝试
- 详细日志:记录每次重试的详细信息,便于排查问题
2.2 京东订单复用优化
改进前:
// 复用失败直接创建新订单
if reusableJdOrder != nil {
// 使用可复用的京东订单
jdOrderId = reusableJdOrder.JdOrderId
cookieId = reusableJdOrder.CookieId
wxPayUrl = reusableJdOrder.WxPayUrl
// 刷新支付链接
if expired {
wxPayUrl, err = s.refreshPaymentUrl(ctx, jdOrderId, payId, cookieId)
if err != nil {
return "", "", "", gerror.Wrap(err, "刷新支付链接失败")
}
}
}
改进后:
// 复用失败后,自动切换到创建新订单,并记录相关历史
if reusableJdOrder != nil {
jdOrderId = reusableJdOrder.JdOrderId
cookieId = reusableJdOrder.CookieId
wxPayUrl = reusableJdOrder.WxPayUrl
// 检查支付链接是否过期
if reusableJdOrder.WxPayExpireAt != nil && gtime.Now().After(reusableJdOrder.WxPayExpireAt) {
// 支付链接已过期,尝试刷新
newWxPayUrl, refreshErr := s.refreshPaymentUrl(ctx, jdOrderId, reusableJdOrder.PayId, cookieId)
if refreshErr != nil {
glog.Warning(ctx, "刷新支付链接失败,将创建新订单", g.Map{
"jdOrderId": jdOrderId,
"error": refreshErr,
})
// 刷新失败,标记为不可复用
_ = s.UpdateJdOrderStatus(ctx, jdOrderId, int(consts.JdOrderStatusExpired), "刷新支付链接失败")
_ = s.RecordJdOrderHistory(ctx, jdOrderId, string(consts.JdOrderChangeTypeInvalid), "", reusableJdOrder.WxPayUrl)
// 记录Cookie刷新失败历史
_ = s.RecordCookieHistory(ctx, cookieId, string(consts.CookieChangeTypeRefreshFail), 0, 0, orderId, 0)
// 清空,准备创建新订单
jdOrderId = ""
cookieId = ""
wxPayUrl = ""
} else {
wxPayUrl = newWxPayUrl
// 更新京东订单的支付链接和过期时间
_ = s.updateJdOrderPaymentUrl(ctx, jdOrderId, wxPayUrl)
isReused = true
}
} else {
isReused = true
}
}
// 如果没有成功复用,创建新的京东订单(带重试机制)
if jdOrderId == "" {
jdOrderId, cookieId, wxPayUrl, err = s.createNewJdOrderWithRetry(ctx, orderId, amount, category)
if err != nil {
return "", "", "", err
}
}
优化的优势:
- 降级处理:复用失败时自动降级到创建新订单
- 完整记录:记录刷新失败、订单失效等所有状态变更
- Cookie管理:刷新失败时记录Cookie的失败历史
- 用户体验:保证订单创建成功率,不因单个环节失败而影响整体流程
2.3 新增的变更类型常量
在 internal/consts/jd_cookie.go 中需要添加的常量(如果还未添加):
// CookieChangeType Cookie变更类型
const (
CookieChangeTypeRefreshFail CookieChangeType = "refresh_fail" // 刷新失败
CookieChangeTypeReplaced CookieChangeType = "replaced" // 被替换
)
// JdOrderChangeType 京东订单变更类型
const (
JdOrderChangeTypeInvalid JdOrderChangeType = "invalid" // 失效
)
3. 改进细节
3.1 日志记录优化
每个关键步骤都添加了详细的日志记录:
glog.Warning(ctx, "刷新支付链接失败,将创建新订单", g.Map{
"jdOrderId": jdOrderId,
"error": refreshErr,
})
glog.Info(ctx, "创建京东订单成功", g.Map{
"orderId": orderId,
"jdOrderId": jdOrderId,
"cookieId": availableCookieId,
"retryCount": retryCount,
})
glog.Error(ctx, "创建京东订单失败,所有Cookie均不可用", g.Map{
"orderId": orderId,
"triedCookies": triedCookies,
"error": lastErr,
})
3.2 历史记录完整性
所有状态变更都会记录到历史表:
- Cookie历史:使用、失败、刷新失败、被替换
- 京东订单历史:创建、绑定、失效、替换
- 用户订单历史:创建、绑定、过期
3.3 错误处理改进
// 明确的错误信息
return "", "", "", gerror.Wrapf(lastErr, "创建京东订单失败,已尝试%d个Cookie", len(triedCookies))
// 保留最后一次错误
if lastErr == nil {
lastErr = gerror.New(consts.ErrCodeCookieNotAvailable)
}
测试建议
单元测试
-
测试重试机制:
- 模拟多个Cookie失败的场景
- 验证重试次数是否正确
- 验证是否避免重复尝试相同Cookie
-
测试订单复用:
- 测试支付链接刷新成功
- 测试支付链接刷新失败后创建新订单
- 测试历史记录是否完整
-
测试Cookie切换:
- 验证Cookie失败后状态更新
- 验证自动切换到下一个Cookie
集成测试
-
端到端测试:
- 创建订单 → 支付 → 提取卡密
- 复用订单 → 刷新链接 → 支付
-
压力测试:
- 并发创建订单
- 验证Cookie分配是否均衡
- 验证系统稳定性
性能影响
优化点
- 减少数据库查询:复用订单时减少不必要的查询
- 批量操作:历史记录使用异步批量写入
- 缓存利用:充分利用Redis缓存减少数据库压力
注意事项
- 重试次数:当前设置为10次,可根据实际情况调整
- 超时控制:建议添加整体超时控制,避免长时间阻塞
- 并发控制:注意订单创建的并发控制,避免竞争条件
向后兼容性
- API接口不变:
CreateOrder方法签名保持不变 - 数据结构不变:不需要修改数据库表结构
- 配置项不变:使用现有的常量配置
部署建议
-
灰度发布:先在小流量环境测试
-
监控指标:
- 订单创建成功率
- Cookie使用分布
- 重试次数统计
- 平均响应时间
-
回滚方案:保留旧版本代码,必要时快速回滚
未来优化方向
- 动态重试次数:根据Cookie池大小动态调整重试次数
- 智能Cookie选择:根据历史成功率优先选择可靠的Cookie
- 异步处理:订单创建改为异步处理,提升响应速度
- 熔断机制:单个Cookie连续失败达到阈值后自动熔断
总结
本次重构主要解决了以下问题:
- ✅ Cookie失败重试:自动切换Cookie,提升订单创建成功率
- ✅ 订单复用优化:刷新失败后自动降级到创建新订单
- ✅ 代码结构优化:文件职责清晰,便于维护和扩展
- ✅ 历史记录完整:所有状态变更都有详细记录
- ✅ 日志体系完善:关键步骤都有日志记录,便于排查问题
重构后的代码更加健壮、可维护,能够更好地应对Cookie失效、京东接口异常等场景。