Golang-微服务-紧急升级-增加接口缓存

1. 背景


API 服务器 timewait 一直下不去
尝试阿里云优化方案, 修改内核配置, 也不管用

前端表现为:

  • 页面访问卡顿
  • 页面丢失(接口504)
  • Postman start_trasfer 参数忽高忽低(100ms-10s)

推测 API 拒绝服务了

2. 分析

  • 监控查看到 io 耗时增加

  • 日志查询到后端微服务没问题, 响应很快

  • Postman 查看接口访问链接时间

  • 阿里云ALB监控页面显示 5xx 状态码明显增加

3. 解决

  • 为热点接口增加缓存
  • 收紧该热点接口限流设置
  • 修改日志级别到 warn (此项操作做完 io 明显下降)

4. 为热点接口增加缓存踩坑纪要

1. ORM缓存

  • 线上业务仍在运行的情况下, 分步热更新 后台微服务
  • 首先尝试为 ORM 加缓存, 因为快, 只需要增加两行代码
cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000)
engine.MapCacher(&user, cacher)

但是这里有坑

不过需要特别注意不适用缓存或者需要手动编码的地方:
当使用了Distinct,Having,GroupBy方法将不会使用缓存
在Get或者Find时使用了Cols,Omit方法,则在开启缓存后此方法无效,系统仍旧会取出这个表中的所有字段。
在使用Exec方法执行了方法之后,可能会导致缓存与数据库不一致的地方。因此如果启用缓存,尽量避免使用Exec。如果必须使用,则需要在使用了Exec之后调用ClearCache手动做缓存清除的工作。

整个 后台 server 的开发工作不仅仅是我一人完成的, 这里也没有去查询是否有用到 Exec 方法, 最终导致用户锁单失败, 超售了
后来紧急回滚了

2. GIN 中间件缓存

基于架构设计, API 承上启下, 实现 HTTP 接口, 调用微服务; API 使用 GIN 框架作为 HTTP 服务框架, 尝试寻找一个 GIN 框架的缓存轮子

  • 官方版本
    不好用, 需要前端配合, 放弃
  • 三方版本
    优点: 中间件实现形式, 方便使用, 性能比官方好一些
    缺点:
    • 只支持 URI 做接口缓存, 但是我这里的需求是 POST 形式, 参数在 body 内, 无法适用
    • 暂不支持 redis 集群作为缓存介质
  • 三方版本PR
    修改了三方版本里只支持URI作为key缓存的情况, 增加了 body 的 hash 为key缓存, 刚好符合要求(用内存形式先上)

5. 小结

  • ORM缓存不可轻易使用, 加了ORM缓存后, 需要回测
  • 接口缓存注意缓存有效期, 根据具体业务需求来定
posted @ 2023-03-16 11:17  GETTOLIVE  阅读(122)  评论(0编辑  收藏  举报