《Unity3D高级编程之进阶主程》第二章,架构(一) - 架构的意义

什么是架构? 架构每天都有人在耳边提起。架构到底是什么,却很少有人说的清楚。

===

网络上解释的,比如,软件架构是一个系统的草图,又比如,软件体系结构是构建计算机软件实践的基础,还有,软件系统架构是一系列相关的抽象模式,用于指导大型软件系统各个方面的设计。说的都对,但是阐述还是过于模糊,懂的人本来就懂不用看,而不懂的人看了还是一头雾水。

‘架构’这个词太抽象,导致难以准确定义,而现在的大部分书本和文章中讨论的’架构‘都是服务器端的部署图,所以大部分人一提到架构就觉得是几台服务器放这里,放那里,用什么软件连接合作,用什么框架开发扩展等等。

我希望能这通过这个章节引导人们将错误的观念纠正过来。实际上架构无处不在,它实质上是解决生活和工作中的问题的一种方案。除了自己着手寻找解决问题的方案外,其他方案,比如直接购买现成的,或者直接放弃,或者以外包以及部分外包的形式,以还有合作模式等来对解决问题,也是切实可行的,其实都是值得考虑的解决问题的方案。我们所求的不是最贵的也不是最高级的,而是最好用的。

在软件系统架构中,架构承担了解决项目从研发到上线运营的方案。前端渲染引擎的选择是自己研发一款引擎,还是使用商业引擎?商业引擎使用Unity3D还是Unreal还是其他?以及怎么用,是和UGUI一起用还是和NGUI一起用?UI里的事件系统如何做统一的处理?AI行为算法是选择行为树还是状态机抑或事件型决策树?数据如何获取和存储?场景如何拆分?是否需要将资源分离出去?是长连接还是短连接?服务器端是用C++还是Java抑或Python?是全部使用关系型数据库还是加入Cache机制?网络协议是用 protocal buff 还是 json 还是 xml 或者使用完全自定义格式等等等。

这些项目中的每个子系统的都有自己的决策方向,而子系统的决策方向,把它们合起来加入一定的关联性就构成了一个完整架构整体,即每个系统、模块、组件都是软件系统架构中的一部分。

优秀的架构师,需要对每个子系统决策的方向要进行深思熟虑,不仅只针对单个系统的决策方向,还要结合其他系统以及整体系统需求的方向进行决策。

在架构设计中,为了能够更好的整理,思考,描述,表达,于是就有了架构图这个东西。架构师把架构中抽象的系统、模块、组件画在图上用圆圈、方块和文字表示,让自己和大家能够更加系统的认识到架构的意图,规范,以及子系统的细节。

一个完整架构图会有很多细节的子系统、或者说子模块架构图,比如UML对象关系图就是一种,它描述了数据类之间的关系,把系统中对象模块用画图的方式描述清楚了。又比如部署图也是其中的一种,它把需要多少种服务器,分别起到什么作用,相互之间的关系描述清楚了,还有时序图,把系统程序调用的次序与流程描述清楚了。这些子系统的架构图合起来构成了一个完整的项目的架构图,最后才有了总体的架构图。如果把子系统架构细节略去,在不关心细节的情况下,描述各系统的合作方式,展现给人的是整体的解决方案,从宏观的角度下看整个项目的布局,会让人一目了然。

为了让更多人理解软件系统架构的,我想把软件系统架构比喻的更切入实际生活一点。

软件系统架构可以理解为是软件程序的架子,和现实中的书架相比有异曲同工之妙,这个架子上有很多大大小小的格子,每个格子里都可以放固定种类的程序。架子有大有小,大的需要花费点去做,小的轻便快捷。

架子的大小是由做设计的设计师决定的,设计师根据客户的需求设计大小,假如放置的空间大,且需要承载的东西多,那么就往空间大的方向设计,能容纳更多的东西,能放置各种不同类型的程序,反之则做小一点,又快,又轻。

架子完成后要拿出去用,如果一有什么不同的情况就倒了或散架了就不算是个好的架子了,所以架子的好坏有几个方面的评估。

一,承载力。

书架上能放多少东西,能放多重的东西是使用者(这里使用者可以为客户,玩家,或程序员)比较关注的点。

从软件架构的程序意义来说,一个架构能承载多少个逻辑系统,代码复杂度扩展到100万行代码代码时是否依然能够有序规范,程序员彼此工作的模块相互依存度有多少,能够承载多少个程序员共同工作因为能工共同工作的架构加速了开发与迭代,这是对软件架构承载力的评定。

从架构的结果上来看,对于服务器来说,当前架构能承受多少人同时访问,日均访问量能承载多少,是承载力的体现。而对于客户端来说,能显示多少UI元素,可渲染多少模型(包括同屏渲染和非同屏渲染),数据交互能达到多少量。

访问量承载太低,访问量一上来就都卡在加载上,大家就不再有这个耐心来看你的产品,运营和宣传部门的导量效果就大打折扣。同样的,客户端渲染承载不了过多元素时,帧率过低,画面卡顿现象严重,产品就不会得到认同。

承载力是重要因素,但并非是唯一关键因素,这个世界这个社会讲究的永远是综合因素,一个点的好坏并不能决定全盘的好坏,而往往木桶效应里最短的那块木板才是。

二,可扩展度。

如果书架上只能放书,这个书架的用途就太单一了,花瓶不能放、箱子不能放、鞋子不能放、袋子不能放、衣服不能放,客户八成不买单。

架子适应不同类型的需求,添加不同类型的系统,不同功能的子系统,是非常必要的。软件架构也是同样的,需要具有高的可扩展度。

而且可扩展度的关键在于,在添加新的子系统后不能影响或者只能尽可能的少量影响其他子系统的运作。假设添加了子系统后,所有系统都得重写或者重构,那就是灾难,前面花去的时间和人力物力精力全部‘浪费’,这是我们不想看到的,因此可扩展度也是衡量好的架构的非常重要标准。

三,易用性。

易用性是架构师最最容易忽视的一个点,有了完整的架构,但不好用,而架构师却还是一心在推动它使用,导致开发效率的下降是常有的。

这就好比,书架上要取个东西,如果取个东西需要先输入密码,再打开门,再剥去袋子,拿出来,把袋子放进箱子,关上门,当放回书架上去时,则再来一遍以上这些所有步骤,实在是太繁琐,即使功能再多,承载力再好,使用者也无法承受这么繁琐的步骤,而且都是机械重复的,精力和注意力都损耗在了没有意义的地方。

易用性决定了架构的整体开发效率,程序员容易上手,子系统容易对接,开发效率自然就高,各模块各部件的编写只需要花一点点精力来关注架构的融合,其他所有精力和注意力都可以全部集中在自己的框架结构上,才能让各系统各尽其职将效率发挥到极致。

四,可伸缩力。

还是用书架比喻,假设我现在没有这么多书和东西要放,房子也不够大,我的书架是否可以折叠缩小到我需要的大小,是可伸缩力的体现。

如果我们制造的书架可随时放大或随时折叠缩小的那就太好。软件架构也是同样的,当需要的承载量没有这么大时,是否可以不使用不需要的功能,化繁为简,只使用需要的部分。

例如从服务器端的角度来说,当需要急速导入大量用户时到做能承载几百万人同时在线,服务器可随时扩展到几百上千台服务器来提高承载量,当访问量骤减,或者平时访问量比较少的情况下,访问量甚至低到只有几十个人在访问时,服务器可缩减到就几台机子在运作,这样大大缩减了服务器费用的开销,可以根据需要而随时变更架构的承载力来节省成本。

而从客户端的角度来说,伸缩力体现在是否能适应大型项目众多人协同开发复杂系统,既能适应大成本消耗下的大项目大作品,也能适应小项目1-3个人团队小而快速的开发环境,小成本小作品极速迭代。

在实际项目中,有时可伸缩力看起来并不是关键的因素,很多人误认为伸缩能力是种程序员的负担,甚至有的项目某些时期根本不需要伸缩力,只需要适应当前的特定时间的需求就可以了。不得不强调可伸缩力在架构中的关键位置,它是深入理解、设计架构的关键因素,是做出优秀的完整的架构的重要因素。

五,容错力以及错误的感知力

书架也会磕磕碰碰的时候,同样也会在某处做工不精时遇到使用后歪斜,如果我们保证不了完全没有问题,至少我们需要保证它不会因为一点点小小的毛病而彻底散架。

软件架构也是同样的,软件中错误、异常、BUG常有,设备何时损坏我们无法预估。容灾力首先起到了不让产品彻底不能使用的作用,有备份方案自动启用,也同时要能够让我们及时得知到问题发生,以及问题的所在,通过EMAIL发送或者通过短信、电话方式通知维护者,并且记录并保存错误信息。

从服务端的角度来说,容灾力包括,数据库容灾能力,应用服务器容灾力,缓存服务器容灾力,以及中心服务器容灾力,每个机子倒下了都需要通知相关中心服务器改变策略,或者监控服务器检测得知该服务器倒下了,更换成备用服务器或者直接更换链路。

从客户端角度来说,容灾力包括当数据发生错误时,是否同样能够继续保持运行而不崩溃,当程序出错时,是否依然能够继续运行其他程序,而不闪退或崩溃甚至再次启动也不能使用的状况发生。所有出现的错误,都能及时的记录并发送到服务器后台存储成为错误日志,便于开发人员能都及时得到详细的错误信息,根据错误信息能够快速找出问题的所在。

在架构中这五项能力缺一不可,某项能力特别突出也不能决定整个架构的好坏,综合因素才是。哪一项比较弱,则问题会不断向该方向聚集,直到最终出现大的问题,甚至崩溃。我们需要一个牢固的,多样化的,好用的,可伸缩的,有韧性的书架,这也是我们在构建架构时所追求的。
其实万物是相通的,木桶原理在各个地方都适用,木桶上仅有一条或几条板比较长没用,其他板都短照样撑不住多少水。说到实际工作生活中就比如,老板CEO是有局限性的,对公司的宏观架构多厉害多好多明智,下面的高管不给力,一切都是白费力气,高管再给力,小弟们不给力,还是一塌糊涂。一个点的好坏并不能决定整体的走向。契合我们的架构理论,最宏观的整体架构,是由所有子系统的架构来支撑的,整体架构虽然比其他子系统的架构都更加重要,但再好的整体架构也并不能起到决定性作用。引申到战争中,也是一样,立于众多溃败下的一两场漂亮的以少胜多的精彩战斗,还是无法扭转全局,因为一个好的将军需要众多好的将士支撑,一个好的司令需要众多好的将领以及更多的好的士兵支撑。综合因素决定了成败,架构也同样如此,如何让所有的因素都朝着好的方向发展是所有架构师最终都需要思考和解决的问题。
· 书籍著作, Unity3D, 前端技术

感谢您的耐心阅读

Thanks for your reading

  • 版权申明

    本文为博主原创文章,未经允许不得转载:

    《Unity3D高级编程之进阶主程》第二章,架构(一) - 架构的意义

    Copyright attention

    Please don't reprint without authorize.

  • 微信公众号,文章同步推送,致力于分享一个资深程序员在北上广深拼搏中对世界的理解

    QQ交流群: 777859752 (高级程序书友会)