切换 fiber coredump ? 你需要理解异步与并发
作者:
| 更新日期:异步与并发是两个概念,但是很容易混淆。
本文首发于公众号:天空的代码世界,微信号:tiankonguse
一、背景
A 服务
很早之前,我负责的 A服务 从 spp 异步框架切换为 fiber 并发框架。
切换之前,我查看了大量的 fiber 资料。
最终得出的结论是,A服务只修改服务配置,重启服务就完成了切换。
当然,这并不代表所有的服务都只需要修改配置即可完成切换。
A服务 可以这样做,是因为我当初设计代码架构时,进行了简单的分层与解耦,从而使得切换没有问题。
PS:当然,也由于我这个服务比较简单,只有一层网络。
B 服务
前段时间,线上遇到一个故障,团队的B服务 CPU 暴涨,但是 cpu 跑到 50% 左右就开始大量失败,最终扩容了很多机器才缓解。
当时我告诉大家一个信息:A服务在 spp 框架下也有 cpu 跑不起来的问题,这个是 spp 框架导致的。后来 A服务在只修改配置就切换到 fiber 框架后,CPU 就可以压的很高了。
于是,同事决定也尝试通过修改 B 服务的配置来切换框架,结果还成功切换过去了,CPU 也可以跑到 100% ,节省不少机器。
只是后来,同事发现 B服务切换到 fiber 后,偶尔数据会不符合预期,最终又回滚到 spp 了。
C 服务
最近,团队新加入了一个小伙伴,领导打算让他来把 C 服务从 spp 切换到 fiber。
领导的信息有限,即看到了 A 服务和 B服务直接修改配置就切换了,虽然 B 服务有点小问题,花点时间去解决就好了。
而我的信息则稍微多一些,我了解 spp 框架与 fiber 框架的运行原理,还了解这两个框架之间的差异,以及不同场景切换的成本。
正文开始
具体来说就是,spp 是异步框架,fiber 是并发框架,而 C 服务代码逻辑非常复杂,存在大量的并发逻辑。
在异步框架中,“并发”逻辑实际上是异步执行的,并没有真正的并发执行。
而在并发框架中,并发逻辑真的是并发执行的,那就会存在并发问题。
异步与并发的关系可能有些人忘记了,后面我稍微展开介绍一下。
二、同步、异步、并发
如下图,假设我们的服务没有依赖的同时向下游拉取两个数据。
伪代码如下:
Net net;
Data data;
net.Add([&data](A& a){ a.PreCpu(data); a.Net(); a.AfterCpu(data); });
net.Add([&data](B& b){ b.PreCpu(data); b.Net(); b.AfterCpu(data); });
net.run();
同步
在同步框架服务中, CPU 的运行时间线是串行的,在网络等待的时候,CPU 是空闲的。
异步
在异步框架中,在网络等待的时候,去做其他事情其他消耗 CPU 的事情。
即网络等待时 CPU 可以分时复用,从而提升 CPU 的利用效率。
多核异步
异步框架利用多核时,就需要开多个线程或者多个进程了。
此时对于同一个请求来说,依旧只能在一个核上运行,即使其他核是空闲的。
例如下图,CPU 2 已经处理完请求2 而空闲了,但是依旧不能处理请求 1的 CPU 逻辑。
并发同步
对于并发同步,其实就是大家熟悉的多线程跑任务,由于和此文关系不大,这里就不展开了。
并发异步
在只有一个核时,异步框架与并发框架区别不大。
但是有多个核时,这种区别就很明显了。
并发的时候,同一个请求的逻辑可以真正的同时运行了。
三、问题所在
其实看了上面关于同步与并发的介绍,大家就可以发现问题了。
在异步框架中,对于同一个请求的代码逻辑,是不存在并发的。
而在并发框架汇总,同一个请求的代码随时都可能运行。
如果并发的时候同时操作同一个数据结构,就会产生所谓的并发问题,从而造成未知的结果。
这就是问题所在。
四、系统的复杂性
如果只是简单的系统,存在并发时,稍加注意就可以解决。
比如通过代码架构设计,避免并发同时读写同一数据。
或者并发读写同一数据之前,先加一个锁也是可以的。
但是对于团队的这个 C 服务,解决这个问题就变得困难了,因为系统的并发关系非常复杂。
下图是系统的一个抽象的简化图。
对于一个请求来说,会创建一个结构体来储存当前请求相关的临时数据,我们一般称为 context。
当然为了和框架自带的 context 做区分,这里我称为 myContext 。
如果代码没有进行分层设计,在一个请求的整个过程中,任何一个环节都可能来读写这个 context 。
如上图,任何一个环节都有一个红色虚线指向 myContext,代表会读写这个 myContext。
更复杂的是,存在并发的数据结构并不仅只有 myContext。
每个环节也是一个对象,而对象内部也可能存在并发来操作自己,以及操作 myContext。
更更复杂的时,这种对象可能是嵌套的。
当然,有没有我也不清楚,这就需要更深入的梳理全局的代码逻辑才知道。
五、最后
其实内部问答系统上经常遇到有人反馈使用 fiber coredump 的问题。
其中几乎所有问题,都是并发问题导致的。
因为以前的框架是异步框架,大家用了很多年了,那样写代码一直没有问题。
而如今时代变了,框架支持真正的并发了。
《完》
-EOF-
本文公众号:天空的代码世界
个人微信号:tiankonguse
公众号ID:tiankonguse-code
本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。