思考(六十三):微服务架构中的时序问题

问题

微服务架构中调用关系异常复杂,容易发生时序问题,而导致系统漏洞

比如,下面的时序图,玩家先买一个道具,然后进副本:

ShopService BattleService MoneyService 1.1 查询 Gold 1.2 购物处理 1.3 扣除 Gold 2.1 查询 Gold 2.2 进入条件检查 ShopService BattleService MoneyService

考虑到外挂、玩家点快了、网络异常等,有可能会导致 2.1 比 1.3 先访问 MoneyService,导致系统漏洞

解决思路

把玩家的每次操作,均视为一次事务

玩家当前事务正在执行过程中时,新请求挂起,而不是并发去执行

因此涉及 2 块编码:

  1. 如何追踪微服务调用链,并做成事务
  2. 入口服务(如 gateway)对事务做处理

第 2 个问题简单

第 1 个问题也有现成的参考或直接拿来用。可以搜索微服务全链路跟踪

微服务全链路跟踪

下面引用下 opentracing 中的一些图解,展示微服务全链路跟踪的过程
摘自 https://opentracing.io/specification/

Causal relationships between Spans in a single Trace


        [Span A]  ←←←(the root span)
            |
     +------+------+
     |             |
 [Span B]      [Span C] ←←←(Span C is a `ChildOf` Span A)
     |             |
 [Span D]      +---+-------+
               |           |
           [Span E]    [Span F] >>> [Span G] >>> [Span H]
                                       ↑
                                       ↑
                                       ↑
                         (Span G `FollowsFrom` Span F)

Sometimes it’s easier to visualize Traces with a time axis as in the diagram below:

Temporal relationships between Spans in a single Trace


––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|> time

 [Span A···················································]
   [Span B··············································]
      [Span D··········································]
    [Span C········································]
         [Span E·······]        [Span F··] [Span G··] [Span H··]

上面 2 副图,解释了微服务全链路调用实际上是个directed acyclic graph (DAG)

directed acyclic graph (DAG) 单向无环图。用程序员的话来说就是,DAG 这丫不会死循环,且可以回溯回 root 节点

因此可以放心做全链路跟踪啦

golang 微服务全链路编码思路

如果微服务间通信都是用 grpc 这种,那么直接拿 opentracing 做下应用就可以了

如果微服务间基础通信模块写的比较奔放,结合 golang 特点 ,最优雅的实现,就用 context 来传递事务ID

自己实现大致思路如下:

  1. 网络层接口支持 context 参数
  2. 网络层接口内部自动序列化 context 参数,并底层自动封包进网络数据
  3. 网络层接口内部自动解析网络数据,并重新生成 context 传递给上层接口
  4. 入口服务(如 gateway)给 context 设置事务ID

其他问题

微服务应用,通常都是针对用户的,比如游戏,绝大多数都是针对具体玩家的操作

这些范畴内,把微服务全链路看成一个事务都是 OK 的

但也有些例外的操作,比如全服型的,某服务自动触发的更新某玩家数据的操作。这种都无法通过入口服务(如 gateway)来让事务串行化

在微服务架构中,通常建议的做法都是服务被动处理事务

某服务自动触发的更新某玩家数据的操作基本上都会有代替做法,把它变成通过入口服务(如 gateway)来让事务串行化

这部分内容有待深究

以上

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fananchong2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值