天天看点

[架构之路-51]:架构师 - 用系统化、结构化思维解决复杂难搞的软件故障问题 - 马克思主义哲学在软件系统中的应用

目录

​​第1章 系统化思维​​

​​1.0 概述​​

​​1.1 深度思考、底层思维:深度​​

​​1.2 全局/整体思考:广度 - 普遍联系、相互影响​​

​​1.3 全局/整体思考:广度 - 局部最优与全局最优​​

​​1.4 动态思考 - 时间、变化​​

​​第2章 结构化思维与解题思路​​

​​2.1 概述​​

​​2.2 解决故障的思路​​

​​步骤1:现象收集:多方面​​

​​步骤2:分析现象背后的可能原因:全面、胆大地假设​​

​​步骤3:求证真正的原因:必须小心地求证​​

第1章 系统化思维

1.0 概述

马克思主义哲学告诉我们:客观事物是由多方面因素、多个对象、多层子系统组成的相互联系、发展变化的有机整体。

软件系统亦然。

系统思维:就是人们运用系统观点,把对象的互相联系的各个方面及其结构和功能进行系统性认识的一种思维方法。

其中,整体性、全局性原则是系统思维方式的核心。这一原则要求人们无论干什么事都要立足整体,从整体与部分、整体与环境的相互作用过程来认识和把握整体。

领导者或架构师,在思考和处理问题的时候,必须从整体出发,把着眼点放在全局上,注重整体效益/整体性能和整体结果。只要合于整体、全局、系统、整机的利益,就可以充分利用灵活的方法来处置。

采用系统思维,就能抓住整体,抓住要害,掌控全局。

采用系统思维,才不片面,不狭隘,不固执。

采用系统思维,才能不失原则,又能使用灵活、高效的方法处置事务,解决棘手的问题。

1.1 深度思考、底层思维:深度

(1)原理:

很多时候,我们看到的软件出错问题地方,并不是出问题的根源的地方。

很多时候,我们看到的问题,往往仅仅是现象,并不是真正原因。

现象与原因之间往往有比较远的距离。

[架构之路-51]:架构师 - 用系统化、结构化思维解决复杂难搞的软件故障问题 - 马克思主义哲学在软件系统中的应用
[架构之路-51]:架构师 - 用系统化、结构化思维解决复杂难搞的软件故障问题 - 马克思主义哲学在软件系统中的应用

(2)案例现象:

OAM在某个特定的状态下,上报了一个Fault,而这个Fault在该状态下是不应该上报的,这是客户看到的现象。

原因在哪里呢?是OAM的问题吗?

(3)案例分析

  • 表层原因与解决办法:因为是OAM上报了给fault,且这种上报不符合Fault上报的预先设计的等级规则,从客户的角度来看, OAM应该屏蔽掉该Fault。
  • 进一步的原因与解决办法:该fault可能是其他模块,如RFSW模块上报的,此时需要RFSW解决为什么在该状态下会上报该Fault, 简单粗暴的解决办法是:RFSW增加逻辑,条件不满足时,屏蔽掉Fault的上报。
  • 进一步查找发现:该fault是底层的FPGA上报的
  • 进一步查找发现:该fault是软件设置的某个FPGA的参数不对导致的。
  • 进一步查找发现:该fault是BBU的L1发送了某个不正确的协议数据导致的。
  • 进一步查找发现:是BBU L1的软件,存在一个业务逻辑的bug。
  • 进一步fix掉这个bug,在特定的状态下就不再上报该fault了。

从上面的分析可以看出,现象与出问题的本质之间有较遥远的距离。技术人员需要多问一个“why”,才能一步步逼近真相,发现出错的根源。

然而,有时候,开发人员,由于项目的压力,以及解决bug的时间限制,往往在没有找到真正原因之前,就在自己可控的本层的代码范围内中把这个问题解决了。现象是消失了,但问题并没有真正的解决。与其说解决了,不如说是绕过去了,隐藏了该问题。一旦隐藏了该问题,那么该问题,一定会未来的某个时候,在其他某个地方,以更加隐蔽的方式的呈现出来。

拔苗助长,就是一个经典的,只看到了问题的表象(植物的高度),没有看到问题本质(植物生长代谢)以及本质性的解决问题的办法。

(4)解决之道

  • 要真正的解决问题,就需要站在全局的视角,透过现象,层层剥离,发掘更深层次的原因。

1.2 全局/整体思考:广度 - 普遍联系、相互影响

(1)原理

[架构之路-51]:架构师 - 用系统化、结构化思维解决复杂难搞的软件故障问题 - 马克思主义哲学在软件系统中的应用

马克思主义哲学告诉我们:万事万物存在着普遍的联系。

软件系统亦然。

特别是一个大型的复杂系统,有由无数个大大小小的软件功能模块有机的组合、交联在一起的。模块与模块之间,子系统与子系统之间,通过方式,如消息、状态、全局变量,存在着某种业务逻辑上的关联和相互作用。有些关联是显性的、有些关联是隐性的。因此,某一个软件模块的局部行为的改变,会导致系统中其他模块受到了影响,甚至影响整个系统。

(2)现象1:解决一个bug,引入更多bug

因此,在工程实践中,经常出现一个神奇的现象:在某个局部解决一个bug,在系统的其他地方引入了更多的bug。于是,陷入了无休止的怪圈中,无论是管理者,还是程序员们,一直在忙碌于各种问题的解决,时刻处于紧张忙碌的状态。

[架构之路-51]:架构师 - 用系统化、结构化思维解决复杂难搞的软件故障问题 - 马克思主义哲学在软件系统中的应用

(3)现象2:解决了一个bug,导致系统的功能越来越僵化、弹性越来越差

在工程实践中,解决一个问题或bug,其实有很多途径,可以在系统的很多层面上解决。

有时候,表层解决最容易,代码修改最方便,但会导致导致系统的功能越来越僵化、弹性越来越差。

有时候,在深层次解决,代码修改会比较麻烦,并且需要程序员熟悉和理解更多的软件模块和流程,但那样的解决方案,系统的设计更加的合理、高效,未来的可扩展性更好。

有时候,由于过细的分工,导致要解决bug的程序员,没有技术能力、没有机会看到全局的视角。

因此,很多情形是,程序员受制于或是项目时间的压力、或解bug的KPI的压力、或是自身能力的限制,就会在表层解决现象性问题,原先的bug现象虽然消失了,但导致系统的功能越来越僵化、弹性越来越差。但没人care,管理者更多的关注解决问题的KPI, 而不是最优的技术方案。

(4)解决之道

  • 站在全局的视角,审视出现的故障的现象,找出问题的真正的根源。
  • 站在全局的视角,在众多解决方案中,选择解决问题的最佳的位置或最近方案。
  • 站在全局的视角,思考局部的改动,会到系统中其他模块造成什么样的影响。
  • 站在全局的视角,给出短期、中期、长期的解决方案。短期方案解决的解决bug KPI问题,中长期的解决方案,解决的系统持续演进的问题。

1.3 全局/整体思考:广度 - 局部最优与全局最优

(1)原理

在深度学习中,梯度下降法要解决的一个根本性问题,就是如何尽可能地找到全局最优解,而不是局部最优解,如下图所示:

[架构之路-51]:架构师 - 用系统化、结构化思维解决复杂难搞的软件故障问题 - 马克思主义哲学在软件系统中的应用

(2)案例分析

在一个复杂的系统中,按照逻辑功能,把系统划分为无数个相对独立的领域。每个领域,都有专门的人来负责,如平台、OAM、传输、RF、L1、L2、L3等。

经常遇到这样的现象:解决问题的办法,可以在不同的层面,比如可以在平台、可以在OAM、可以在传输、或在L1、L2、L3。此时,每个模块的负责人,从自身的立场出发,希望代码的改动或优化,尽量降低对自身模块的影响,以保留更多的资源解决更Critical的问题,这就导致,解决方案往往不是技术和业务上最优的,而是从项目管理来的角度来看,最优的。有时候,最后的方案,更多的是看参与技术讨论的个人的强势的程度,而不是全局的最优方案。

(3)解决之道

这时候,就需要有人,特别是架构师,能够站在全局和整体的角度,协调各方人员,包括技术人员、项目管理人员等,基于如下的因素,给出全局最优的方案,甚至需要给出短期和中期的解决方案(当然,并不是所有的解决都需要短期和中期的解决方案)

  • 人力资源的effort
  • 不同方案技术实施难度
  • 不同方案的合理性
  • 项目管理的KPI

全局思考:就是无论是分析问题还是解决问题,都要从全局视角进行分析,不要只局限在自己的熟悉的技术领域,不要只从自己负责或熟悉的领域出发,固执的坚持自己局部的立场和角度。

1.4 动态思考 - 时间、变化

马克思主义哲学认为,万事万物处于各种动态变化之中,“时变“是一个系统的本质特征。

软件系统也是如此。

(1)在嵌入式系统中,不随时间变化的情形:

  • 组合逻辑电路:电路的信号输出,只与输入信号有关,与电路自身当前的状态无关。
  • 线程安全的函数:这样的函数,内部只有局部变量,没有全局变量,无论多少个线程调用该函数,该函数的输出只取决于输入。

(2)在嵌入式系统中,动态变化无处不在:

  • 硬件的时序逻辑:电路的信号输出,只与输入信号有关,还与电路自身当前的状态相关。
  • 线程非安全的函数:这样的函数,内部包含全局变量,因此,函数的输出不仅仅取决于函数的输入,还取决于不同线程调用函数的顺序和时机。除此之外,线程非安全的函数还需要通过线程间互斥和同步机制,规避对全局变量的冲突性访问。
  • 易变性函数:这样的函数,内部会读取硬件的寄存器,这些寄存器的数值不是确定性不变的,而是易变的,这导致,这样的函数,即使是单线程调用,其内部逻辑和输出结果,不仅仅取决于函数的输入,还与硬件的寄存器的值相关,而硬件寄存器的值变化,是独立于之外的。
  • 软件系统的状态机:软件系统采取是什么的行为,不仅仅取决于软件系统外部的事件类型,还与系统当前的状态相关,相同的外部事件,内部状态不同时,软件系统的行为反应是不相同的。
[架构之路-51]:架构师 - 用系统化、结构化思维解决复杂难搞的软件故障问题 - 马克思主义哲学在软件系统中的应用
  • 软件系统的时序图:

时序图又名序列图、循序图。

时序图展现的是:软件系统中多个对象之间,通过特定时间顺序的消息进行动态协作的关系。

时序图展现的是:一个软件系统的“有序”性、一个系统的有条不紊的人为设计。

时序图展现的是:一个软件系统并非是无序的各种事件的动态变化,并非无序与杂乱无章。

软件系统中的大量的业务场景,都是通过时序图来展现的 。

[架构之路-51]:架构师 - 用系统化、结构化思维解决复杂难搞的软件故障问题 - 马克思主义哲学在软件系统中的应用

因此,对大部分软件的功能,不能像刻舟求剑一样,只看得到静态的逻辑或事件。动态和时变才是软件系统的根本。

(3)在设计一个软件系统时

要充分考虑系统的这种动态变化性。

  • 状态机设计
  • 线程间同步
  • 线程间互斥
  • 时序图

(4)解决bug,定位问题时

动态变化性,给系统的故障定位带来了极大的麻烦。要确定一个系统故障问题,就必须清晰的理解系统的上下文、时序图、以及当前的状态。

幸运的是,当前绝大部分的软件系统,都是well design的系统。系统所有的动态变化,包括按照时间变化和按照状态变化,都是预先设计好的。

在解决问题时,必须站在宏观的立场、站在全局的视角,审视各种“无序”、杂乱无章中的“有序”和预先设计的流程、流程与流程之间的关系。特别是流程之间的嵌套关系、依赖关系、相互作用的关系,而理解这些复杂的流程关系,必须要站在全局的视角、系统的视角。

第2章 结构化思维与解题思路

2.1 概述

结构化简单的讲,就是套路,就是模式。

2.2 解决故障的思路

步骤1:现象收集:多方面

  • 收集问题对客户业务需求的影响
  • 收集问题对目标系统的影响
  • 收集网管看到的异常信息
  • 收集网络看到的故障报警
  • 收集Log中看到的异常信息

步骤2:分析现象背后的可能原因:全面、胆大地假设

  • 必须全面:站在全局、系统架构的视角把控求解问题的宏观脉络和思路,鱼骨图就是一种手段。
  • 按照软件模块分层的角度进行排查
  • 按照系统设计的逻辑流程进行排查
  • 按照软件设计的时序进行排查
  • 按照软件设计的状态机进行排查
  • 要能大胆的假设、根据经验大胆的推测各种可能性
  • 最好对各种假设的可能性进行排序
  • 最好能按照可能性的大小顺序,从可能性最大的开始,逐一排查,既不是随性查,也不是东一榔头西一棒子
  • 从问题的现象出发,以现象为锚点,避免偏差太大,南辕北辙。

步骤3:求证真正的原因:必须小心地求证

  • 对假设进行求证的过程必须小心谨慎、尽量避免想当然的推测,必须有要有足够的证据。
  • 求证的手段:源代码、log、网管、问题复现、增加测试代码、预测性模拟等手段。

继续阅读