软件架构的演进
一、基本概念
在介绍架构之前,为了避免部分读者对架构设计中的一些概念不了解,下面对几个最基础的概念进行介绍。
1、什么是分布式
系统中的多个模块在不同服务器上部署,即可称为分布式系统,如Tomcat和数据库分别部署在不同的服务器上,或两个相同功能的Tomcat分别部署在不同服务器上。
2、什么是高可用
系统中部分节点失效时,其他节点能够接替它继续提供服务,则可认为系统具有高可用性。
3、什么是集群
一个特定领域的软件部署在多台服务器上并作为一个整体提供一类服务,这个整体称为集群。 如Zookeeper中的Master和Slave分别部署在多台服务器上,共同组成一个整体提供集中配置服务。 在常见的集群中,客户端往往能够连接任意一个节点获得服务,并且当集群中一个节点掉线时,其他节点往往能够自动的接替它继续提供服务,这时候说明集群具有高可用性。
4、什么是负载均衡
请求发送到系统时,通过某些方式把请求均匀分发到多个节点上,使系统中每个节点能够均匀的处理请求负载,则可认为系统是负载均衡的。
5、什么是正向代理和反向代理
系统内部要访问外部网络时,统一通过一个代理服务器把请求转发出去,在外部网络看来就是代理服务器发起的访问,此时代理服务器实现的是正向代理;
当外部请求进入系统时,代理服务器把该请求转发到系统中的某台服务器上,对外部请求来说,与之交互的只有代理服务器,此时代理服务器实现的是反向代理。
简单来说,正向代理是代理服务器代替系统内部来访问外部网络的过程,反向代理是外部请求访问系统时通过代理服务器转发到内部服务器的过程。
软件架构的发展经历了从单体架构、垂直架构、SOA架构到微服务架构以及到现在最新的service mesh(网格服务架构)的过程。借用dubbo的网站架构发展图和说明:
二、单体架构
1、特点
(1)所有的功能集成在一个项目工程中。
(2)所有的功能打一个war包部署到服务器。
(3)应用与数据库分开部署。
(4)通过部署应用集群和数据库集群来提高系统的性能。
此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。
2、优点
项目架构简单,前期开发成本低,周期短,小型项目的首选。
3、缺点
(1)全部功能集成在一个工程中,对于大型项目不易开发、扩展及维护。
(2)系统性能扩展只能通过扩展集群结点,成本高、有瓶颈。
(3)技术栈受限。
三、垂直架构
1、特点
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。
此时用于加速前端页面开发的Web框架(MVC)是关键。
2、优点
(1)项目架构简单,前期开发成本低,周期短,小型项目的首选。
(2)通过垂直拆分,原来的单体项目不至于无限扩大。
(3)不同的项目可采用不同的技术。
3、缺点
(1)全部功能集成在一个工程中,对于大型项目不易开发、扩展及维护。
(2)系统性能扩展只能通过扩展集群结点,成本高、有瓶颈。
四、SOA架构-分布式服务架构
1、SOA即面向服务的架构,如dubbo。
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
2、优点
(1)把模块拆分,使用接口通信,降低模块之间的耦合度。
(2)把项目拆分成若干个子项目,不同的团队负责不同的子项目。
(3)增加功能时只需要在增加一个子项目,调用其它系统的接口就可以。
(4)可以灵活的进行分布式部署。
3、缺点
系统之间交互需要使用远程通信,接口开发增加工作量。
五、微服务架构
微服务是一种架构风格。一个大型的复杂软件应用,由一个或多个微服务组成。系统中的各个微服务可被独立部署,并且各个微服务之间是松耦合的,服务内部是高内聚的。每个微服务仅关注于完成一件任务并很好的完成该任务。
1、特点
(1)将系统服务层完全独立出来,并将服务层抽取为一个一个的微服务。
(2)微服务遵循单一原则。
(3)微服务之间采用RESTful等轻量协议传输。
2、优点
(1)服务拆分粒度更细,有利于资源重复利用,提高开发效率。
(2)可以更加精准的制定每个服务的优化方案,提高系统可维护性。
(3)微服务架构采用去中心化思想,服务之间采用RESTful等轻量协议通信,相比ESB(企业级服务总线)更轻量。
(4)适用于互联网时代,产品迭代周期更短。
3、缺点
(1)微服务过多,服务治理成本高,不利于系统维护。
(2)分布式系统开发的技术成本高(容错、分布式事务等),对团队挑战大。
4、微服务架构需要解决的技术难点
(1)这么多服务,怎么找?
通过zookeeper做服务注册信息的分布式管理。当服务上线时,服务提供者将自己的服务信息注册到ZK,并通过心跳维持长链接,实时更新链接信息。服务调用者通过ZK寻址,根据可定制算法,找到一个服务,还可以将服务信息缓存在本地以提高性能。当服务下线时,ZK会发通知给服务客户端。主流的注册中心:zookeeper、Eureka、consul、etcd。
(2)服务之间如何通信?
因为所有的微服务都是独立的Java进程跑在独立的虚拟机上,所以服务间的通信就是IPC(inter process communication),已经有很多成熟的方案。比如基于HTTP的REST或者Thrift、dubbo等。
(3)这么多服务,服务挂了怎么办?
可以采取如下策略:重试机制、熔断机制、限流/降级、负载均衡策略等等。
六、几种架构之间的区别
七、技术选型
技术选型是一个项目的基础,一旦技术选型出现问题,后期要换用其他技术栈,代价是非常大。一般情况下,技术选型会遵循以下几个原则:
1、选择熟悉的技术
一个新项目最好不要使用超过30%的新技术,对于不熟悉的技术,在使用过程中出现的风险是不可控的。而且从团队建设上,任何一位技术Leader,如果不能得到下属的技术尊重,必将受到惩罚。当然也不能完全不用新技术,完全不用势必会走向另一个极端,即裹足不前失去技术前进的机会。总的来说,选择熟悉的技术主要是为了在保持稳定性的同时适当引入新技术从而使整个团队保持技术先进性。
2、选择成熟活跃的技术
选择成熟的技术可以避免踩不必要的坑,碰到问题也可以找到丰富的资料,也可以得到更多的社区支持。当然这是针对应用场景而言,也有一些团队专门就是做新技术预研,专门去踩坑,看是否有应用新技术的可行性。技术不光是考虑成熟度还要考虑技术活跃度,活跃度在某个程度上也间接说明了该技术的应用广度,同时也能得到更多的支持。
3、选择前进的技术
选择一个技术的最低标准是:技术的生命周期必须显著长于项目的生命周期。为什么需要确保所选择的技术不断前进,那是因为当前技术发展是非常快速的,技术的前进不仅仅取决于它本身,也和大环境发展密切相关。例如早期的delphi, silverlight, 现在都已被淘汰,如果不幸选择了类似这样的技术栈,对项目的伤害是巨大的,甚至可能直接导致项目无法进行下去。需要记住的是:没有最好的技术,只有最合适当前业务的技术。总的来说,好的技术栈要永远跑在用户需求前面。
八、架构演进的五条原则
既然要对架构进行升级重构,那么有没有一些基本的准则,指导我们避免一些坑呢?基于此,我们尝试总结了架构演进的五条原则。
1、确定当前的架构现状
每次架构演进,一定是针对当前架构的,所以必须非常清楚当前的架构现状和问题。清楚现状,明白目标,才能逐步改进,向目标前进。
2、确定重构的目的和必要性
在进行重构时,需要明白这些问题:即架构重构的原因是什么:是为了满足业务需要还是只是觉得架构比较落伍?此外还应该思考除了架构重构之外,是否有别的备选方案。重构的价值何在,是否一定要进行架构重构?
3、定义“重构完成”的标准
为每一次架构演进定义清晰的重构目标和成功标尺,方便得到反馈及时进行调整。
4、渐进式重构
尽量将重构过程进行分解,每次都进行小的改进,尽快展示成果并得到反馈,在迭代中逐步完善。
5、远离虚的东西
例如使用热门的技术,使用不成熟的技术。
架构重构要脚踏实地,根据实际需要以及团队的技术背景,选择合理的重构方案。
九、参考资料
(1) https://www.cnblogs.com/linjiqin/p/10074004.html
(2) https://www.cnblogs.com/duanxz/p/3514781.html
(3)https://www.cnblogs.com/lcyhjx/p/11186122.html
(4) https://www.cnblogs.com/dotnet-arch-system/p/8232879.html
(5) https://www.cnblogs.com/fengzheng/p/5847441.html
(6)https://www.cnblogs.com/miketwais/p/architect.html
(7) https://www.cnblogs.com/xzmiyx/p/9956875.html
(8) https://segmentfault.com/a/1190000018626163 (架构演进过程)
(9) https://zhuanlan.zhihu.com/p/42115757 (有关于网格服务架构service mesh的描述)
(10) https://blog.51cto.com/14279308/2476567 (架构演进过程)