分布式软件理论总结

软件系统的本质

软件是现实的抽象,讨论抽象的本质是困难的,让我们一起在现实中思考。小到一支笔,大到一部汽车,这些产品的出现,使我们在现实生活中得到了方便。这里说的方便,是指因为使用了这些产品,降低了成本,提高了效率。在没有笔的时代,想要记录信息需要结绳、岩画或篆刻,这是高成本的,效率也很低。同样的,没有汽车的时代,想要到达另一个城市,会因为恶劣天气而被迫中途搁置,相应的通行时间也会比现在长得多。进一步的思考,笔与汽车的共同点又在哪里呢?

笔与汽车,这些产品是为了满足人们的各类生活需求而发明的。即,人们因为现实需要,而发明或改进了产品,产品是为了帮助人们更好的生活而存在。同样的,软件系统也是如此,人们出于远距离沟通交流需要,发明电话拨号系统;因为更随时随地的信息多样化交流,发明了各种互联网IM产品。

软件系统是依托于人们现实需求而存在,用以辅助人们更好的生活,它是现实世界在虚拟世界的抽象。同样的软件系统也存在着兴衰淘汰,一款软件刚问世时,受欢迎程度总是处于低谷,存在现实世界对其接受适应的时间窗。突破时间窗,进而逐渐闻名天下,此时依托此软件又会催生出许多子软件链(如chromium的众多壳浏览器、SVN的众多客户端)。随着技术革新,软件产业也会更新换代,跟不上时代的软件系统会逐渐退出市场(如vista操作系统的短命)。但市场总是存在需要的,类似的软件在倒下后总会有后继者,如浏览器,这几乎在国内,每家互联网公司都想做或者已经在做。

不良设计的局限性

在软件系统的发展初期,适用面狭窄,功能单一、用户少、价值不够高,造成对软件系统研发的不重视,成本投入低。相应的,软件所带来的经济收益也是有限的。此时的软件系统往往谈不上架构,往往是一个软件系统承载了所有功能,单个功能模块没有边界,逻辑分散,而各个功能模块之间的耦合关系是散乱的。

在软件系统有机会成长起来后,带来了一定的经济收益。我们会思考软件系统的功能增多,更适应于用户(市场需要),或者考虑增强原有用户黏性,此时会对软件系统提出更多要求。而初期功能模块散乱的堆叠,对迫切需要的可扩展性带来了的麻烦,紧耦合的架构造成牵一发而动全身的问题,新功能的增加,往往意味着巨大地改造成本。勉强加上一些功能后,整个软件系统简直是乱作一团,就像是一堆红豆绿豆,这样的软件系统,我们称之为集中式软件系统。

集中式的软件系统还对重构带来挑战,随着功能需求越来越频繁的提出,往往意味着需要更短的版本迭代周期。现有系统无法灵活扩展,意味着需要对整个软件系统进行重构,而等到软件散乱性膨胀到一定程度,重构几乎变成不可完成的任务,就算是系统初始负责人,也无法评估重构带来的风险与收益究竟谁更多?

停不下来的运动员

集中式的软件系统在濒危阶段,开发团队往往面临两难,团队任何人都知道急需重构,但因为没有决策权,最高决策领导也顾虑着市场利益,而不可能给出重构所需的资源(时间、人力、软硬件)。在愈发杂乱的系统上进行维护和新功能叠加,这让团队内的每个人都需要指数级的投入成本,往往还达不到市场需要的质量。

就像田径400米接力比赛中,只能跑第一棒的运动员,本应在交棒后停下来休息,自我调整。而由于接手下一棒的运动员迟迟不能到位,运动员只能咬牙坚持跑第二棒,但迈出的每一步都越来越累,没法再像刚开始保持加速度。更令人担忧的是,此时裁判还吹响了冲刺哨,要求运动员进行冲锋。这样,运动员只有倒下了。相应的,软件系统到此时,开发团队成员会加速流失,新招进来的人也很难理解整套系统的协作,经常顾此失彼,从而导致最终的系统失败。

这也就是为什么CTO必需对技术团队保持深入理解,同时还应有对产品、开发的最高决策权,以支持技术团队在适时进行系统级别的重构,让失去体力的软件系统下线休息,换上更适合的新软件系统上线,从而更好地满足公司的战略需求,这是非常有必要的。

向敏捷开发过渡

在软件系统有机会从集中式软件模式,过渡到积木型的软件模式后。系统原有是100%的功能堆叠到一个系统,现在变成了多个积木,也就是软件子系统,每个积木只负责其中的部分功能,积木间的协作,从而拼装出完整的软件系统。

快速交付

集中式的软件往往灵活性低下,这体现在很多方面。

1.设计的灵活性,想要以好的设计替换掉不再适应设计方案,会遭遇无法评估改造成本。

2.构建的灵活性,软件功能过于集中,导致一个小的编译问题,都会影响整个软件的构建,就像走钢丝一样,必需每一步都完美无缺才能安全走到终点。

3.测试的灵活性,测试任务因为功能互相紧耦合而变得繁重,无法评估已经做好的功能是否会受到影响。

4.部署的灵活性,运维无法根据系统的流量特性来优化软硬件配置,如JVM调优,Load Balance等。

5.修复的灵活性,这一点往往在集中式软件中是一个优势,在线上出现问题,只需要简单的分析少量的运行日志即可定位问题,这在积木性系统中是一个软肋。

敏捷开发的主要优势就在于,合理的利用分治思想,将复杂的功能的系统模块化处理,拆分成由只有简单功能的子系统而拼凑出来的完整系统,每一个子系统可以交付到小团队来维护,甚至与有单独的运维人员来进行保障。

可维护性

这是一个巨大的转变,首当其冲的就是可维护性,只需要定义一套灵活的通信协议,子系统之间通过这套协议进行通讯,我们在对子系统内部的功能进行维护时,不必担忧其他子系统受到干扰。这也存在一个前提,能够封装在一个子系统的功能模块集合,必须是内聚型的,它们几乎很少对外层子系统产生耦合,或者通过统一的出口进行耦合关联。

可扩展性

其次是软件的可扩展性,新功能的开发,只需要新加一个子系统,扩展通讯协议,就可以满足要求,这对团队内的任何一个人都是令人振奋的。

隔离性

积木型的软件构建,还给了我们保持专注的可能。现在我们可以为软件进行动静分离设计,以适应不同的最佳部署方式。可以按照系统流量特性,应用CQRS架构,提供更好的局部性能。进一步的还可以为强共用性的功能进行独立剥离出来,譬如单独的文件系统负责所有的文件服务,以在避免各个积木内部的重复造轮子,独立的服务还为以后的:可维护性、伸缩性带来了诸多方便。

质量可控

同时,软件的质量可以得到保证,测试部门可以明确的针对某个软件子系统进行测试,而不需要每次系统上线都进行整体测试,工作量的降低,在相等的时间内,有了更多的时间进行问题修复,这往往意味着质量的提高。

积木型的软件,是对积木之间通讯协议的高要求,实际上,我们需要引入一整套消息通讯中间件来解决这个问题,在SOA和EDA架构中,最为关键的就是MQ协议的设计了。

松耦合的模式还带来局部失败和最终一致性的问题,可能会给用户造成短时间迷惑,但不影响最终的数据状态统一,这在传统软件领域往往是不可接受的,但进入到互联网后,在系统层面往往需要进行权衡,是市场机遇重要?还是少部分的用户利益重要?这个问题需要每一个互联网人的思考,产品是不是要满足每一个人的要求呢?

分布式系统的利与弊

软件的构成

概括的讲,软件普遍是由三部分组成:接入、逻辑、存储。其中接入是可能没有的,比如定时任务型软件,由操作系统时间来触发,不需要外界的主动调度。而逻辑和存储,很难有软件是不需要的。而比如典型的在线社交服务,常规的构成可以分为:聊天服务、长连接服务、推送服务、好友信息服务、文件服务、推荐服务、广告服务。这些按业务功能相关性而划分的服务,没有哪一个可以脱离接入、逻辑和存储的。这些服务从本质上来说大部分都是OLTP(Online Transaction Processing),就是将现实生活中的沟通交流需求转移到了互联网进行。

SOA VS EDA

什么是SOA?

SOA VS Mirco Service

什么是EDA?

分场景使用

Design for failure

Fast fail VS Retry

无状态

应用中心和任务中心

单点服务向多点服务的转变

原因:
性能要求,多节点同时参与服务(按流量权重分发,负载均衡;按读写流量分发,读写分离)。
允许少部分节点失败,更可靠的运行。

数据存储跨机分片,同时每片在多机存在复制集。计算资源无状态,本身就可以动态管理。便捷的扩容缩容(伸缩性)。

因业务分拆,降低耦合粒度,降低系统扩展成本(可扩展性),更高的可维护性。

带来的问题。
系统内部改造,支持多节点转变。

分布式事务,事务补偿。

分布式存储

分布式访问

容忍最终一致性。

Reference

Talk is cheap,show me the code.