在早期,单体架构的这种扩展方式可以很好地满足使用需求,但随着时间的推移,这种方式就会产生很多问题,具体表现如下。
1. 应用复杂度增加,更新、维护困难
一个简单的应用会随着时间的推移而逐渐变大。一旦应用变得庞大而又复杂,开发团队将会面临很多问题,其中最主要的问题就是这个应用太复杂,以至于任何单个开发者都很难进行二次开发或维护。
2. 易造成系统资源浪费
虽然使用负载均衡的方式可以对项目中的服务容量进行水平扩展,但由于传统单体架构的代码中只有一个包含所有功能的WAR包,所以在对服务容量扩容时,只能选择重复地部署这个WAR包来扩展服务能力,而不仅仅是扩展了所需的服务。这样就会导致其他不需要扩展的服务也进行了相应的扩展,但这些扩展是不需要的,因此这种方式会极大地浪费资源。
3. 影响开发效率
当一个应用越大时,启动时间就会越长。开发和调试的过程中,如果有很大一部分时间都要在等待中度过,那么必然会对开发效率有极大的影响。
4. 应用可靠性低
传统单体应用架构在运行时的可靠性比较低,当所有模块都运行在一个进程中时,如果任何一个模块中出现了一个Bug,可能会导致整个进程崩溃,从而影响到整个应用。
5. 不利于技术的更新
传统单体应用架构一旦选定使用某些技术,则后期的开发和扩展将在这些技术的基础上实现。如果需要更改某种技术,则可能需要将整个应用全部重新开发,这种成本是非常大的。
当然,传统单体应用架构的问题还不只这些,但出现这些问题的根本原因可以说就是由于传统单体架构中一个WAR包内包含了系统的所有服务功能所导致的。随着业务变得越来越多,问题也就越来越多。
1.1.2 如何解决传统应用架构的问题
针对传统单体架构的问题,大部分企业通过SOA(ServiceOriented Architecture,面向服务的架构)来解决上述问题。SOA的思路是把应用中相近的功能聚合到一起,以服务的形式提供出去,因此基于SOA架构的应用可以理解为一批服务的组合。
SOA将原来的单体架构按照功能细分为不同的子系统,然后再由各个子系统依赖服务中间件(这里指企业服务总线Enterprise Service Bus,简称ESB)来调用所需服务。
使用SOA可以将系统切分成多个组件服务,这种通过多个组件服务来完成请求的方式有很多好处,具体如下。
·把项目拆分成若干个子项目,不同的团队可以负责不同的子项目,从而提高开发效率。
·把模块拆分,使用接口通信,降低了模块之间的耦合度。
·为企业的现有资源带来了更好的重用性。
·能够在最新的和现有的应用之上创建应用。
·能够使客户或服务消费者免予服务实现的改变所带来的影响。
·能够升级单个服务或服务消费者而无需重写整个应用,也无需保留已经不再适用于新需求的现有系统。
虽然使用SOA解决了单体架构中的问题,但多数情况下,SOA中相互独立的服务仍然会部署在同一个运行环境中(类似于一个Tomcat实例下,运行了很多web应用)。和单体架构类似,随着业务功能的增多,SOA的服务会变得越来越复杂。本质上看,单体架构的问题并没有因为使用SOA而变得更好。
针对单体架构和SOA的问题,许多公司(如Amazon、eBay和NetFlix)通过采用微处理结构模式解决了系统架构中的问题。其思路不是开发一个巨大的单体式的应用,而是将应用分解为小的、互相连接的微服务。随着微服务的使用,微服务架构的思想也随之产生。
从图1-4中可以看出,微服务架构已将传统单体架构中的订单服务、商品服务和用户服务拆分为了独立的服务,其中的每一个服务都是一个独立的应用,可以访问自己的数据库,这些服务对外提供公共的API,并且服务之间可以相互调用。
注意:微服务和微服务架构是两个不同的概念。微服务强调的是服务的大小,它关注的是某一个点,而微服务架构是一种架构思想,需要从整体注意微服务和微服务架构是两个不同的概念。微服务强调的是服务的大小,它关注的是某一个点,而微服务架构是一种架构思想,需要从整体上对软件系统进行全面的考虑。
1.2.2 微服务架构的优点
与传统单体应用架构相比,微服务架构有很多优点,具体表现如下。
1. 复杂度可控
微服务架构在将应用分解的同时,规避了原本复杂度无止境的积累。每一个微服务专注于单一功能,并通过定义良好的接口清晰地表述服务边界。由于体积小、复杂度低,每个微服务可由一个小规模开发团队完全掌控,易于保持高可维护性,并提高了开发效率。
2. 可独立部署
由于微服务具备独立的运行进程,所以每个微服务都可以独立部署。当某个微服务发生变更时,无需编译、部署整个应用。由微服务组成的应用相当于具备一系列可并行的发布流程,使得发布更加高效,同时降低了对生产环境所造成的风险,最终缩短应用交付周期。
3. 技术选型灵活
微服务架构下,技术的选型是多样化的。每个团队都可以根据自身服务的需求和行业发展的现状,自由选择最适合的技术。由于每个微服务相对简单,当需要对技术进行升级时,所面临的风险较低,甚至完全重构一个微服务也是可行并容易的。
4. 易于容错
当架构中的某一组件发生故障时,在单一进程的传统架构下,故障很有可能在进程内扩散,导致整个应用不可用。在微服务架构下,故障会被隔离在单个服务中。若设计良好,其他服务可通过重试、平稳退化等机制实现应用层面的容错。
5. 易于扩展
单个服务应用也可以实现横向扩展,这种扩展可以通过将整个应用完整地复制到不同的节点中实现。当应用的不同组件在扩展需求上存在差异时,微服务架构便体现出其灵活性,因为每个服务可以根据实际需求独立进行扩展。
6. 功能特定
每个微服务都有自己的业务逻辑和适配器,并且一个微服务一般只完成某个特定的功能,例如商品服务只管理商品、客户服务只管理客户等。这样开发人员可以完全地专注于某一个特定功能的开发,而不用过多地考虑其他,从而提高开发效率。
除此之外,微服务架构还有很多其他优势,由于篇幅有限,这里就不一一列举了,但从微服务架构的优势可以看出,使用微服务可以很好地解决传统单体架构中的问题。
1.2.3 微服务架构的不足
微服务架构除了有上面所讲的各种优点外,还存在着一些不足,这些不足的具体表现如下。
1. 开发人员必须处理创建分布式系统的复杂性
·开发工具(或IDE)是面向构建传统的单体应用程序的,不为开发分布式应用程序提供全面功能上的支持。
·测试更加困难。在微服务架构中,服务数量众多,每个服务都是独立的业务单元,服务主要通过接口进行交互,如何保证依赖的正常,是测试面临的主要挑战。·开发人员必须实现服务间的通信机制。
·实现用例跨多个服务时,需要面对使用分布式事务管理的困难。
·实现跨多个服务的用例,需要团队之间进行仔细的协调。
2. 部署的复杂性
在部署和管理时,由许多不同服务类型组成的系统的操作比较复杂,这将要求开发、测试及运维人员有相应的技术水平。
3. 增加内存消耗
微服务架构用多个服务实例取代了1个单体应用程序实例,如果每个服务都运行在自己的JVM中,那么有多少个服务实例,就会有多少个实例在运行时的内存开销。
1.2.4 微服务架构与SOA的区别
1.3 如何构建微服务架构
1.3.1 微服务的拆分
对于一般的公司而言,实践微服务有非常大的技术挑战,所以并不是所有的公司都适合将单体架构拆分成微服务架构。一般来说,微服务架构比较适合未来有一定的扩展复杂度,且有很大用户增量预期的应用,例如一些新兴的互联网公司应用。这些公司在创业初期,不可能买大量的或很贵的机器,但是又必须考虑应对成功后巨量的用户问题,这时微服务架构就成了最好的选择。除此之外,对于那些项目规模较大、业务复杂度较高,且需要长期跟进的项目,也适合考虑使用微服务架构。
在决定使用微服务架构后,所面临的另一个问题就是如何将系统拆分为微服务。对于微服务的拆分,可以参考如下几点建议。
·通过业务功能分解并定义与业务功能相对应的服务。
·将域驱动设计分解为多个子域。
·按照动词或用例分解,并定义负责特定操作的服务,例如一个负责完成订单的航运服务。
·通过定义一个对给定类型的实体或资源的所有操作负责的服务来分解名词或资源,例如一个负责管理用户账户的账户服务。
1.3.2 微服务架构的组件
在正式学习如何搭建微服务架构之前,我们先来了解一下微服务架构中涉及的一些常见组件名称及其作用。
·服务注册中心:注册系统中所有服务的地方。
·服务注册:服务提供方将自己调用地址注册到服务注册中心,让服务调用方能够方便地找到自己。
·服务发现:服务调用方从服务注册中心找到自己需要调用服务的地址。
·负载均衡:服务提供方一般以多实例的形式提供服务,使用负载均衡能够让服务调用方连接到合适的服务节点。
·服务容错:通过断路器(也称熔断器)等一系列的服务保护机制,保证服务调用者在调用异常服务时快速地返回结果,避免大量的同步等待。
·服务网关:也称为API网关,是服务调用的唯一入口,可以在这个组件中实现用户鉴权、动态路由、灰度发布、负载限流等功能。
·分布式配置中心:将本地化的配置信息(properties、yml、yaml等)注册到配置中心,实现程序包在开发、测试、生产环境的无差别性,方便程序包的迁移。
1.3.3 微服务架构的搭建
在图1-5中,部署了一系列的微服务,每个微服务都会访问自己的数据库(Database)。当这些微服务启动时,会将其信息注册到服务注册中心(Service Registry),在客户端发送请求时,请求首先会被API网关(API GateWay)拦截,API网关会读取请求数据,并从注册中心获取对应的服务信息,然后API网关会根据服务信息调用所需的微服务。
小提示:图1-5中展示的只是一个简单的微服务架构,然而要判断一个架构是否是微服务架构,还需要满足以下几点要求。
·根据业务模块划分服务种类。
·每个服务可独立部署且相互隔离。
·通过轻量级API调用服务。
·服务需保证良好的高可用性。
只有满足以上几点要求的架构,才能称之为微服务架构,所以在搭建微服务架构时,一定要注意这些问题。
1.3.4 微服务架构的技术选型
在微服务架构中,不同的组件(包括微服务实例、注册中心和API网关等组件)需要根据不同的情况来选取相应的技术,那么我们可以使用哪些技术呢?本小节将对微服务架构中各个组件可使用的技术,以及本书所选用的技术进行简单介绍。
1. 微服务实例的开发
微服务的开发可以选用的框架技术有Spring团队的SpringBoot、Jboss公司的WildFly Swarm和Java EE官方的微服务框架KumuluzEE等。
2. 服务的注册与发现
架构中服务的注册与发现功能,可以使用的技术有SpringCloud Eureka、Apache Zookeeper、Consul、Etcd和Dubbo等,它们都是用于服务注册和发现的技术。
3. 负载均衡
负载均衡可以使用的技术有Spring Cloud Ribbon和Dubbo等。
4. 服务容错
服务容错的技术可以选用Hystrix,在Spring Cloud的子项目中包含Spring Cloud Hystrix。
5. API网关
架构中的API网关服务,可以使用的技术有Spring CloudZuul、Spring Reactor、Netty或NodeJS等。
6. 分布式配置中心
分布式配置中心可以使用Spring Cloud Config。
7. 调试
微服务应用的测试工作可以使用Swagger。Swagger是当前最受欢迎的REST API文档生成工具之一,它提供了强大的页面测试功能来调试每个RESTful API。
8. 部署
微服务的官方文档中推荐使用Docker来打包和部署微服务。由于Docker是一个开源的应用容器引擎,具有可移植性强、启动速度快等特点,所以适合跑一些轻量的应用。
9. 持续集成
为了实现服务的自动化部署,我们可以通过Jenkins搭建自动化部署系统,并使用Docker进行容器化封装。
在上面的技术选型中,从微服务注册与发现、负载均衡、容错、API网关和分布式配置中心组件的可选技术内,我们都看到了Spring Cloud的身影。实际上,Spring Cloud的子项目中,已经提供了构建微服务所需的所有解决方案。
从图1-6中可以看出,我们会使用Spring Boot实现微服务实例的开发,使用Spring Cloud Eureka来实现服务的注册与发现,使用Spring Cloud Hystrix的断路器功能来实现服务容错,使用Spring Cloud Ribbon实现服务间的负载均衡,使用SpringCloud Zuul实现服务网关,使用Spring Cloud Config作为分布式配置中心,使用Swagger对微服务进行测试,并使用Jenkins的持续集成功能来实现自动化部署。
微服务架构中各个组件的技术选型有很多,对于已经实施过微服务并且项目自成体系的公司来说,Spring Cloud可能并没有太大的吸引力,但对于还未实施微服务或项目没有自成体系的公司来说,Spring Cloud将是一个非常好的选择。
小提示:除了Spring Cloud之外,Dubbo也是目前国内比较流行的分布式服务框架,它们都具备分布式服务治理相关的功能,都能够提供服务注册、发现、路由和负载均衡的能力。相比之下,Spring Cloud提供了更加完整的一套企业级分布式云应用的解决方案,包含了微服务组件中的方方面面,并能够结合Spring Boot、Docker实现快速开发的目的,而Dubbo只有Spring Cloud的一部分功能。由于二者具体的实现方式不同,因此并没有好坏之分。企业在选用时,需根据自身情况选择。