每个人都能在实践中总结出自己的架构设计方法论,或称之为架构设计风格。以下仅是我个人风格倾向。
演进式设计
架构设计不可能一步到位。首先,计划永远赶不上变化,需求变化太快了;其次,一个一步到位的系统也是极为耗费人力的,但现在来说,先做一个MVP(最小可用版本)再迭代才更现实;再次,个人能力也不足。
因此,我个人的做法是:“做一望三”。也就是,尽可能先考虑到这个系统远期的“最终形态”,我们假定它是这个系统三年后的样子,并简单设计出来,作为长期目标;然后只将其中当前来说最重要的那部分挑出来,即大约6个月到1年时间里能迭代出来的系统形态,把这个作为当下的短期目标。
ROI至上,时刻关注成本
ROI = 收益 / 成本。
很多人的设计是完全不考虑成本因素的。这里特指服务器、硬件相关的成本。尤其是一些大厂,擅长大开大合,疯狂招人,疯狂迭代,疯狂推广,疯狂堆机器,疯狂裁员。这里不讨论这种做法的优劣性,毕竟这些大厂之所以能在激烈的竞争中脱颖而出,也证明了这种大开大合的方法是有可取性的。只是个人更喜欢这种更稳健更务实一些的做法。
我习惯从技术选型开始就要时刻考虑成本的因素。比如说,某个xxx功能对时延的要求非常高,需要专门搭一组高性能的缓存集群,这合算吗? 再比如,KV数据库使用纯内存型的还是SSD型的。再比如,同样的服务,自建还是用云厂商提供的,用哪家云厂商,用社区开源版还是云商Saas/Paas版?
当然,这也要求有足够的对价格和成本的敏感度,起码要知道哪些环节会产生费用、大体的计费方式如何、大致的价格对比等。
使用较成熟的选型方案
如果是核心系统,我会优先选择对我来说最成熟的方案。而如果是边缘系统,则会考虑拿来试验一些新产品、新技术。
为什么是“对我来说最成熟”? 因为一个方案是否成熟,一是看业界,二是看自身。如果这个技术在业界已经很成熟了,但自己团队里没有懂行的人,还是要慎选。这也是我哪怕是在做ERP时也会选择使用Golang而非Java的原因。
充分利用云商的资源
现在的云服务厂商们提供了大量自研的好用的服务,如果利用得当,作用很大。
因为同样的功能,如果云商已经做好现成的服务了,大概率是比自研来得稳定的。虽然要付费,但算上开发成本和时间成本,还是非常合算。
随便举几个例子:
- AWS S3。 几乎可以认为是所有云服务里可用性最高的,AWS的金字招牌。需要归档的重要数据可以考虑使用S3作为最终的存储。因为它可能是普通人能接触到的最高可用性的产品了。
- 阿里云 Maxcompute。 阿里云自研的大数据平台,存算分离,兼容各种主流的大数据产品,一下子, OLAP, Map Reduce, Flink, Spark, Graph... 全有了,包含所有主流的大数据场景。对于中小型团队来说,几乎不可能搭建出比这更好的大数据平台了。
- Azure 语音相关功能。语音识别转文字,文字转语音等,效果吊打所有的国内平台,使用API直接接入。
- 函数式计算。 各主要厂商都有类似的产品,比如 AWS Lambda。适合于触发式的任务、实时任务、短期促销这类场景。不需要建立服务器,以函数的方式独立运行。 (当然,这些服务的定层,在云商那里还是有服务器的)。比如有一个任务,一天只执行一次,而一次执行需要几百台服务器,如果长期开服务器放在那里,非常浪费,此功能就非常适合这个场景。
文档化
整个架构需要从不同的角度分别提供文档+示意图,详见
我的习惯是,在文档里还要把设计的背景、原因、关键设计的思路也要列上去,以后回来翻的时候非常有用。因为很多设计到后面是只知其然不知其所以然,甚至在改来改去中已经与原意相去十万八千里,代码越来越乱,最后没人敢动。
尽可能无状态
如果服务里的“状态”太重,会带来很多额外的复杂度。比如集群的扩缩容将变得麻烦。
因此,如果有得选,我希望我的服务是尽可能无状态的,这样它可以非常灵活地随意扩缩容。如果不行,我也希望尽可能轻状态,即减少服务里的状态,或尽可能将状态收敛到少数功能等。