一 软件应用架构演进

随着互联网的发展,使用互联网的人群越来越多,软件应用的体量越来越庞大和复杂,传统的单体应用可能不足以支撑大数据量以及高并发场景,应用的架构也随之进行演变,从最开始的单体应用架构到分布式(SOA)架构再到今天比较火的微服务架构,以及服务网格架构。

应用系统的高可用架构 应用系统架构演进_分布式架构

1.1 单体架构

1.1.1 简单单体结构

单体架构比较初级,典型的三级架构,前端(Web/手机端)+中间业务逻辑层+数据库层。这是一种典型的Java Spring mvc。其架构图如下所示:

应用系统的高可用架构 应用系统架构演进_分布式架构_02

单体架构的应用比较容易部署、测试, 在项目的初期,单体应用可以很好地运行。然而,随着需求的不断增加, 越来越多的人加入开发团队,代码库也在飞速地膨胀。慢慢地,单体应用变得越来越臃肿,可维护性、灵活性逐渐降低,维护成本越来越高。下面是单体架构应用的一些缺点:

  1. 复杂度高
    以一个百万行级别的单体应用为例,整个项目包含的模块非常多、模块的边界模糊、 依赖关系不清晰、 代码质量参差不齐、 混乱地堆砌在一起。可想而知整个项目非常复杂。 每次修改代码都心惊胆战, 甚至添加一个简单的功能, 或者修改一个Bug都会带来隐含的缺陷。
  2. 技术选择难
    在变得越来越大的同时,我们的应用所使用的技术也会变得越来越多。这些技术有些是不兼容的,就比如在一个项目中大范围地混合使用C++和Java几乎是不可能的事情。在这种情况下,我们就需要抛弃对某些不兼容技术的使用,而选择一种不是那么适合的技术来实现特定的功能。
  3. 部署频率低
    随着代码的增多,构建和部署的时间也会增加。而在单体应用中, 每次功能的变更或缺陷的修复都会导致需要重新部署整个应用。全量部署的方式耗时长、 影响范围大、 风险高, 这使得单体应用项目上线部署的频率较低。 而部署频率低又导致两次发布之间会有大量的功能变更和缺陷修复,出错率比较高。
  4. 阻碍技术创新
    单体应用往往使用统一的技术平台或方案解决所有的问题, 团队中的每个成员 都必须使用相同的开发语言和框架,要想引入新框架或新技术平台会非常困难。
  5. 扩展难

是这种扩展方式极大地浪费了资源。就以上图所展示的情况为例:在一个服务中,某个组成的负载已经达到了90%,也就是到了不得不对服务能力进行扩容的时候了。而同一服务的其它三个组成的负载还没有到其处理能力的20%。由于Monolith服务中的各个组成是打包在同一个WAR包中的,因此通过添加一个额外的服务实例虽然可以将需要扩容的组成的负载降低到了45%,但是也使得其它各组成的利用率更为低下。

1.1.2 集群单体结构

1.1.2.1 为什么需要集群

在单体架构中,为了提升应用的并发作业能力和防止应用的单节点故障(一个Tomcat挂了,应用就挂了)我们通常会对应用做集群,这里的集群指的是把应用进行复制多个相同的应用一起工作来提高作业能力,多个应用做的是相同的事情。就如同我们生活中的场景"收银",一个收银台不足以支撑超市大量客户的结账流程,所以需要多个收银台同时工作,多个收银台都是做的相同的收银工作,这就是集群,如下图:

应用系统的高可用架构 应用系统架构演进_SOA_03

1.1.2.2 负载均衡

当应用做了集群之后作业能力得到提升,能够处理更高的并发请求,同时产生了一个新的问题,就是客户端的请求应该如何相对平局的分发到集群中的多个应用呢?这就需要负载均衡器了。

应用系统的高可用架构 应用系统架构演进_微服务_04

这里的Agent就是一个负载均衡器,它可以按照某种算法(轮询,ip_hash等等)将请求路由到不同的后端服务器上,同类型的负载均衡器还有如“HAproxy”,“LVS”等,这里不展开讨论。

负债均衡算法(Nginx)

  • 轮询(round robin) : 依次将请求分配到各个后台服务器中,默认的负载均衡方式
  • 权重(weight) : 根据权重值将请求分配到后台服务器中,权重值越大,分配比例越高
  • IP_HASH:按照ip地址进行hash运算,同一ip的请求会被分配到相同的机器上
  • url_hash : 根据请求的url的hash值将请求分到不同的机器中。
  • fair:根据服务器响应时间来分发请求,时间越短分发的请求越多

1.2 分布式架构

1.2.1 简单分布式

中级架构,分布式应用,中间层分布式+数据库分布式,是单体架构的并发扩展,将一个大的系统划分为多个业务模块,业务模块分别部署在不同的服务器上,各个业务模块之间通过接口进行数据交互。数据库也大量采用分布式数据库,如redis、ES、solor等。通过LVS/Nginx代理应用,将用户请求均衡的负载到不同的服务器上。其架构图如下所示:

应用系统的高可用架构 应用系统架构演进_应用系统的高可用架构_05

1.2.2 SOA

SOA是面向服务的架构,它的思想是每个子应用可以通过网络通信协议向其他子应用提供服务或者消费服务,SOA也是分布式架构,我们可以简单的理解为SOA把分布式架构划分成表示层和服务层,服务层中包含了业务逻辑和相关流程,只需要对外暴露服务即可,表现层负责处理和页面的交互。这样的划分好处在于系统之间调用的方便性,如用户子系统只需要调用订单子系统的服务层即可完成应用之间的通信。这样的结构划分提高了应用的重用性,业务逻辑也变得可组合。如图:

应用系统的高可用架构 应用系统架构演进_应用系统的高可用架构_06

1.2.3 小结

该架构相对于单体架构来说,这种架构提供了负载均衡的能力,大大提高了系统负载能力,解决了网站高并发的需求。另外还有以下特点:

  1. 降低了耦合度
    把模块拆分,使用接口通信,降低模块之间的耦合度。
  2. 责任清晰
    把项目拆分成若干个子项目,不同的团队负责不同的子项目。
  3. 扩展方便
    增加功能时只需要再增加一个子项目,调用其他系统的接口就可以。
  4. 部署方便
    可以灵活的进行分布式部署。
  5. 提高代码的复用性
    比如service层,如果不采用分布式rest服务方式架构就会在手机wap商城,微信商城,pc,android,ios每个端都要写一个service层逻辑,开发量大,难以维护一起升级,这时候就可以采用分布式rest服务方式,公用一个service层。
    缺点 : 系统之间的交互要使用远程通信,接口开发增大工作量,但是利大于弊。

1.3 微服务架构

微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于HTTP的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等。另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。

应用系统的高可用架构 应用系统架构演进_应用系统的高可用架构_07

微服务架构特点如下:

  1. 易于开发和维护
    一个微服务只会关注一个特定的业务功能,所以它业务清晰、代码量较少。 开发和维护单个微服务相对简单。而整个应用是由若干个微服务构建而成的,所以整个应用也会被维持在一个可控状态。
  2. 技术栈不受限
    在微服务架构中,可以结合项目业务及团队的特点,合理地选择技术栈。例如某些服务可使用关系型数据库MySQL;某些微服务有图形计算的需求,可以使用Neo4j;甚至可根据需要,部分微服务使用Java开发,部分微服务使用Node.js开发。
    微服务虽然有很多吸引人的地方,但它并不是免费的午餐,使用它是有代价的。使用微服务架构面临的挑战。
  3. 易于扩展
    扩展时只需要扩展自己的微服务就OK了。
  4. 运维要求较高
    更多的服务意味着更多的运维投入。在单体架构中,只需要保证一个应用的正常运行。而在微服务中,需要保证几十甚至几百个服务服务的正常运行与协作,这给运维带来了很大的挑战。
  5. 重复劳动
    很多服务可能都会使用到相同的功能,而这个功能并没有达到分解为一个微服务的程度,这个时候,可能各个服务都会开发这一功能,从而导致代码重复。尽管可以使用共享库来解决这个问题(例如可以将这个功能封装成公共组件,需要该功能的微服务引用该组件),但共享库在多语言环境下就不一定行得通了。

1.4 服务网格

springcloud netflix作为微服务框架使用时,基础组件服务注册中,配置中心,网关等还需要自己开发不太方便,虽然这个问题在后来 的springcloud alibaba基本得以解决。单这期间,ServiceMesh网格服务的理炼被提出来,强调开发者只管自己微服务的开发,基础组件不用开发。所以ServiceMesh正在大厂里面实践。

应用系统的高可用架构 应用系统架构演进_应用系统的高可用架构_08

无论是Springlcoud 或者ServiceMesh基本上都要用到k8s,但是由于k8s等环境的搭建与维护变得很复杂,所以云原生,在世界各地流行。云原生强调,我们开发得应用直接是大型云厂商(阿里云,腾讯云,华为云等),不用再关注底层k8s等环境的搭建,所以很省事!但这不是一般小公司能玩的。耗钱呀!

应用系统的高可用架构 应用系统架构演进_应用系统的高可用架构_09

1.5 小结

  • 单体架构
    中小型应用使用
  • 分布式架构
    大型项目-代码重用多
  • 微服务&服务网格架构
    大型项目-不提倡代码重用
    整体评估项目大小,如果项目一直小用单体架构就OK,否则用分布式或者微服务也OK