1.分布式服务架构:原理、设计与实战 --- 分布式微服务架构设计原理

1.1 从传统单体架构到服务化架构
	1.1.1 JEE架构
		JEE是以面向对象的Java编程语言为基础,扩展了java平台的标准版,是java平台企业版的简称。

		JEE将企业级软件架构分为三个层次:web层,业务逻辑层和数据存取层,每个层的职责分别如下:
			1.web层:负责与用户交互或者对外提供接口
			2.业务逻辑层:为了实现业务逻辑而设计的流程处理和计算处理模块
			3.数据存取层:将业务逻辑处理的结果持久化以待后续查询,并维护领域模型中对象的生命周期。

		JEE 平台将不同的模块化组件聚合后运行在通用的应用服务器上,如WebLogic,WebSphere,JBoss等。这也包含Tomcat,但tomcat仅仅是实现了JEE Web规范的
	web容器。JEE平台是典型的二八原则的一个应用场景,它将80%通用的域业务无关的逻辑和流程封装在应用服务器的模块化组件里,通过配置的模式提供给应用程序访问,
	应用程序实现20%的专用逻辑,并通过配置的形式来访问应用服务器提供的模块化组件。

		JEE时代典型的架构如下:
			1.web容器(UI组件1,UI组件2,...)    => 组合业务逻辑
			2.EJB容器(业务组件1,业务组件2,...)  => 数据存取ORM
			3.数据库
		JEE时代的架构以及对企业级应用的整体架构进行了逻辑分层,包括上面提到的web层,业务逻辑层和数据存取层。不同的层级有自己的职责,并从功能类型上划分层级,
	每个层级的职责单一。在这一时期,由于在架构上把整体的单体系统分成具有不同职责的层级,对应的项目管理也倾向于把大的团队分成不同的职能团队,主要包括:用户交互
	UI团队,后台业务逻辑处理团队,数据存取ORM与DBA团队等。
		因此,在分层架构下需要对项目管理过程中的团队职责进行职责划分,并建立团队交流机制。根据康威定律,设计系统的组织架构时,最终产生的设计等价于组织的沟通
	结构,通俗来说,团队的交流机制应与架构分层交互机制相对应。
		但是,每个层次的多个业务逻辑的实现会被放在同一应用项目中,并且运行在同一个JVM中。另外,由于JEE主要用于企业级应用开发,面向的用户较少,所以尽管JEE支持
	web容器和EJB容器的分离部署,这个时代的大多数项目仍然部署在同一应用服务器上并跑在一个JVM进程中。

	1.1.2 SSH架构
		在JEE开始流行但没有完全奠定其地位的时候,开源软件Struts,Spring和Hibernate开始崭露头角,很快成为行业内企业的开源框架标配(简称SSH),JEE规范中的
	各种计数如EJB,迅速失去了进一步的发展机会。Web MVC 框架Struts 在用户交互的UI层进一步划分了前端的职责,将用户交互层划分为视图,模型和控制器三大块。在
	那个时代,Struts MVC 模型几乎服务于大多数企业服务的web项目。
		后来,开源框架Spring的发布,更加改变了JEE一开始制定的战略目标。Spring框架作为逻辑层实现的核心容器,使用起来简单,方便,灵活,几乎大部分开发者完全
	倒向了Spring开源派。Spring框架有2个核心:IOC和AOP。
		Spring IOC 指的是控制反转,将传统EJB基于容器的开发改造成普通的Java组件开发,并且在运行时由Spring容器统一管理和串联,服务于不同的流程,在开发过程
	中对Spring容器没有强依赖,便于开发,测试,验证和迁移。使用EJB实现一个服务化组件Bean时,需要依赖于多个容器接口,并需要根据容器的规则进行复杂的xml配置,
	测试需要依赖于应用服务器的环境,有诸多不便;使用Spring框架则不然,开发业务逻辑时每个业务逻辑的服务组件都是独立的,而不依赖于Spring框架,借助Spring容器
	对单元测试的支持,通过对下层依赖服务进行Mock,每个业务组件都可以在一定范围内进行单元化测试,而不需要重启重型的容器来测试。
		Spring对AOP的支持是Spring框架成功的另外一个因素。AOP代表面向切片的编程,通常适用于使用面向对象方法无法抽象的业务逻辑,例如:日志,安全,事务,应用
	程序性能管理(APM)等,使用它们的场景并不能用面向对象的方法来实现和表达,而需要使用切片来表达,因为它们可能穿插在程序的任何一个角落。在Java的世界里,AOP
	的实现方式有三种:
		1.对java字节码进行重新编译,将切面插入字节码的某些点和面上,可以使用cglib库实现
		2.定制类加载器,在类加载时对字节码进行补充,在字节码中插入切面,增加了除业务逻辑之外的功能,JVM自身提供的Java Agent机制就是在加载类的字节码时,通过
		增加切面来实现AOP的。
		3.JVM本身提供了动态代理组件,可以通过它实现任意对象的代理模式,在代理的过程中可以插入切面的逻辑,可以使用Java提供的APIProxy.newProxyInstance()和
		InvocationHandler来实现。

		另外,AspectJ 是实现AOP的专业框架和平台,通过AspectJ 可以实现任意方式的字节码切面,Spring 框架完全支持 AspectJ。

		到现在为止,SSH 开源标配框架中有了UI交互层的Struts 框架和业务逻辑实现层的 Spring 框架,由于面向对象领域的模型与关系型数据库存在着天然的屏障,所以
	对象模型和关系模型之间需要一个纽带框架,也就是我们常说的ORM框架,它能够将对象转化为关系,也可以将关系转换为对象,于是,Hibernate 框架出现了。Heibernate
	通过配置对象与关系表之间的映射关系,来指导框架对对象进行持久化和查询,并且可以让应用层开发者像执行sql异议进行对象查找。这大大减少了应用层开发人员写sql的
	时间。然后,随着时间的发展,高度抽象的ORM框架被证明有性能瓶颈,因此,后来大家更倾向于使用更加灵活的MyBaits来实现ORM层。	

		这一时代的SSH框架与JEE时代的架构类似,可分为三个层次:实现交互UI接口的 Web MVC 层,实现业务逻辑的 Spring 层及实现对象关系映射的 Hibernate 层,
	每个层级的实现比 JEE对应的层次更简单,更轻量级,不需要开启整个应用服务器即可验证和测试,极大提高了开发效率,这得益于 Spring 框架的控制反转的理念。
		由于这一时代的企业级软件服务的对象仍然是企鹅曰,用户量并不大,因此,大多数企业里的SSH架构最终会被打包到同一个JEE规范的War包里,并且部署在Apache 
	Tomcat Web 容器里,因此,整个架构还是趋向于传统的单体架构,业务逻辑仍如耦合在一个项目中。
		这一时代的职能团队的划分仍然停留在层次上,与JEE架构下的职能团队划分类似,划分为前端团队,后端业务逻辑研发团队和DBA团队。

	1.1.3 服务化架构
		从JEE时代到SSH时代,服务的特点仍然是单体化,服务的粒度抽象为模块化组件,所以组件耦合在一个开发项目中,并且配置和运行在一个JVM进程中。如果某一个
	模块化组件需要升级上线,则会导致其他没有变更的模块化组件同样上线,在严重情况下,对某个模块化组件的变更,由于种种原因,会导致其他模块化组件出现问题。
	另外,在互联网异军突起的情况下,传统JEE和SSH无法满足对海量用户发起的高并发请求进行处理的需求,无法突破耦合在一起的模块化组件的性能瓶颈,单一进程已经
	无法满足需求,并且水平扩展的能力也是有限的。
		为了解决上述问题,SOA出现了。SOA代表面向服务的架构,俗称服务化。SOA将应用程序的模块化组件通过定义明确的接口和契约联系起来,接口是采用重力的方式
	进行定义的,独立于某种语言,硬件和操作系统,通常通过网络通信来完成,但是并不局限于某种网络协议,可以是底层的TCP/IP,可以是应用层的http,也可以是消息
	队列,甚至可以是约定的某种数据库存储形式。这使得各种各样的系统中的模块化组件可以以一种统一和通用的方式进行交互。
		对比JEE和SSH时代的模块化组件后发现,SOA将模块化组件从单一进程中进一步拆分,形成独立的对外提供服务的网络化组件,每个网络化组件通过某种网络协议对外
	提供服务。这种架构的特点如下:
		1.soa定义了良好的对外接口,通过网络协议对外提供服务,服务之间表现为松耦合性,松耦合性具有灵活的特点,可以对服务流程进行灵活组装和编排,而不需要对
		服务本身做改变。
		2.组成整个业务流程的每个服务的内部结构和实现在发生改变时,不影响整个流程对外提供的服务,只要对外接口不变,则改变服务内部的实现机制对外部来说是透明的
		3.soa在这一时代的数据通信格式通常为xml,因为xml标记定义在大规模,高并发通信过程中,冗余的标记会给性能带来极大的影响,所以后来被json所取代
		4.soa通过定义标准的对外接口,可以让底层通用服务进行下沉,供多个上层的使用方同时使用,增加了服务的可重用性。
		5.soa可以让企业最大化的使用内部和外部的公共服务,避免重复造轮子。

		要彻底理解SOA时代的服务化发展情况,我们必须理解SOA的两个主流实现方式:Web Service 和 ESB。
		1.Web Service
			Web Service 技术是 SOA 服务化的一种实现方式,它使得运行在不同的机器及操作系统上的服务的互相发现和调用成为可能,并且可以通过某种协议交换数据。
			每个服务之间是对等的,并且互相是解耦的,通过WSDL定义的服务发现接口进行访问,并同构SOAP协议进行通信。SOAP协议通常是一种在http或者https通道
		上传输xml数据来实现的协议,但是每个服务都要依赖中心化Web Service目录来发现现存的服务。

			Web Service 的工作原理如下:
				1.服务提供者 Web Service 2 和 Web Service 3 通过 UDDI 协议将服务注册到 Web Service 目录服务中。
				2.服务消费者 Web Service 1 通过 UDDI 协议从 Web Service 目录中查询服务,并获得服务的 WSDL 服务描述文件。
				3.服务消费者 Web Service 1 通过 WSDL 语言远程调用和消费 Web Service 2 和 Web Service 3 提供的服务。

			通过这个过程,要改造一个新的业务流程,可以从 Web Service 目录中发现现有服务,并最大限度的重用现有服务,经过服务流程的编排来服务新的业务。

		2.ESB
			ESB是企业服务总线的总称,是用于设计和实现网络化服务交互和通信的软件模型,是SOA的另外一种实现方式,主要用于企业化信息系统的集成服务场景中。
		Mule 是企业服务总线的一个实现。
			在SOA服务化发展之前,企业对信息化系统进行了初步建设,这些企业信息化系统由异构技术栈实现:不同的开发语言,操作系统和系统软件为了快速响应新的
		市场,完全使用新计划重建所有的信息化系统是不现实的,在现有的服务系统上增加新的功能或者叠加新的服务化系统的方法更加可行。这需要对这些现有的信息化
		系统和新增的信息化系统进行组合。SOA凭借其松耦合性的特性,正好应用于这一场景,使得企业可以按照服务化的方式来添加新服务或者升级现有服务,来解决新
		业务对流程编排的需要,甚至可以通过不同的渠道来获得外部服务,并与企业的现有应用进行组合,来提供新的业务场景所需要的信息化流程。
			ESB 也适用于事件处理,数据转化和映射,消息和事件异步队列顺序处理,安全和异常处理,协议转换和保证通信服务的质量等场景。

			ESB服务没有中心化的服务节点,每个服务提供者都是通过总线的模式插入系统,总线根据流程的编排负责将服务的输出进行转换并发送给流程要求的下一个
		服务进行处理。这里我们可以看到,ESB的核心在于企业服务总线的功能和职责,如下所述:
			1.监控和控制服务之间的消息路由
			2.控制可插拔的服务化的功能和版本
			3.解析服务之间交互和通信的内容和格式
			4.通过组合服务,资源和消息处理器来统一编排业务需要的信息处理流程
			5.使用冗余来提供服务的备份能力

			根据以上,我们看到企业服务总线是 ESB 的核心要素,所有服务都可以在总线上插拔,并通过总线的流程编排和协议转换能力来组合实现业务处理能力。


1.2 从服务化到微服务 
	1.2.1 微服务架构的产生 
		随着互联网企业的不断发展,互联网产品需要服务的用户量逐渐增加,海量用户发起的大规模,高并发请求是企业不得不面对的,前面介绍的SOA服务化系统能够分解
	任务,让每个服务更加简单,职责单一,更易于扩展,但无论是Web Service 还是 ESB,都有时代遗留问题。
		Web Service 的问题如下:
			1.依赖中心化的服务发现机制
			2.使用soap通信协议,通常使用xml格式来序列化通信格式,xml格式的数据冗余太大,协议太重
			3.服务化管理和治理设施并不完善

		ESB 的问题如下:
			1.ESB 虽然是 SOA 实现的一种方式,却更多体现了系统集成的便利性,通过统一的服务总线将服务组合在一起,并提供组合的业务流程服务。
			2.组合在 ESB 上的服务本身可能是一个过重的整体服务,或者是传统的 JEE 服务等。
			3.ESB 视图通过总线来隐藏系统内部的复杂性,但是系统内部发复杂性仍然存在。
			4.对于总线本身的中心化的管理模型,系统变得影响的范围经常会随之扩大

		微服务架构倡导将软件应用设计成多个可独立开发,可配置,可运行和可维护的子服务,子服务之间通过良好的接口定义通信机制,通常使用restful风格的api
	形式来通信,因为restful风格的api通常是在http或者https通道上传输json格式的数据来实现,http协议具有跨语言,跨异构系统的优点,当然,也可以通过底层
	的二进制协议,消息队列协议等进行交互。这些服务不需要中心化的统一管理,每个服务的功能可自治,并且可以由不同的语言,系统和平台实现。
		微服务架构致力于松耦合和高内聚的效果,与soa和esb相比,不再强调服务总线和通信机制的多样性,通常通过restful风格的api和轻量级的消息通信协议来完成。
	微服务架构不是为了拆分而拆分,真正的目的是通过对微服务进行水平扩展解决传统的单体应用在业务急剧增长时遇到的问题,而且由于拆分的微服务系统中专业的人做
	专业的事情,人员和项目的职责单一,低耦合,高内聚,所产生的问题的概率就会降低到最小。

	1.2.2 微服务架构与传统单体架构的对比 
		微服务特点:
			1.微服务把每一职责单一的功能放在一个独立的服务中
			2.每个服务运行在一个单独的进程中
			3.每个服务有多个实例在运行,每个实例可以运行在容器化的平台中,达到平滑伸缩的效果
			4.每个服务有自己的数据存储,实际上,每个服务应该有自己独享的数据库,缓存,消息队列等资源
			5.每个服务应用有自己的运营平台,以及独立的运营人员,这包括技术运维和业务运营人员;每个服务都高度自治,内部的变化对外部透明
			6.每个服务都可根据性能需求独立的进行水平伸缩

		传统单体架构特点:
			1.传统单体架构将所有模块化组件混合后运行在同一个服务JVM进程中
			2.可对包含多个模块化组件的整体JVM进程进行水平扩展,而无法对某个模块化组件进行水平扩展
			3.某个模块化组件发生变化时,需要所有的模块化组件进行编译,打包和上线
			4.久而久之,模块间的依赖会不清晰,互相耦合,互相依赖

	1.2.3 微服务架构与SOA服务化的对比 
		事实上微服务架构与 SOA 服务化架构并不冲突,它们一脉相承,微服务架构是服务化架构响应特定历史时期的使用场景的延续,是服务化进行升华并落地的一种
	实现方式。soa 服务化的理念在微服务架构中仍然有效,微服务在soa服务化的基础上进行了演进和叠加,形成了适合现代化应用场景的一个方法论。

		微服务与SOA的不同:
			1.目的不同
				1.soa服务化涉及的范围更广一些,强调不同的异构服务之间的协作和契约,并强调有效集成,业务流程编排,历史应用集成等,典型代表为web service
				和ESB。
				2.微服务使用一系列的微小服务来实现整体的业务流程,目的是有效的拆分应用,实现敏捷开发和部署,在每个微笑服务的团队里,减少跨团队的沟通,让
				专业的人做专业的事情,缩小变更和迭代影响的范围,并达到单一微服务更容易水平扩展的目的。
			2.部署方式不同
				1.微服务将完整的应用拆分成多个细小的服务,通常使用敏捷扩容,缩容的docker技术来实现自动化的容器管理,每个微服务运行在单一进程内,微服务的
				部署互相独立,互补影响。
				2.soa服务化通常将多个业务服务通过组件化模块方式打包在一个war包里,然后统一部署在一个应用服务器上。
			3.服务粒度不同
				1.微服务倡导将服务拆分成更细的粒度,通过多个服务组合来实现业务流程的处理,拆分到职责单一,甚至小到不能再拆分。
				2.soa对粒度没有要求,在实践中服务通常是粗粒度的,强调接口契约的规范化,内部实现可以更粗粒度。


1.3 微服务架构的核心要点和实现原理 
	1.3.1 微服务架构中职能团队的划分 
		传统单体架构将系统分成具有不同职责的层次,对应的项目管理也倾向于将大的团队划分成不同的职能团队。主要包括:用户交互UI团队,后台业务逻辑处理团队与
	数据存取ORM团队,DBA团队等。每个团队只对自己家分层的职责负责,并使用对方提供的组件服务质量保证。如果其中一个模块化组件需要升级,更新,那么这个变更会
	涉及不同的分层团队,即使升级和变更的改变很小,也需要进行跨团队沟通:需求阶段需要跨团队沟通产品功能,涉及阶段需要跨团队沟通设计方案,开发阶段需要跨团队
	沟通接口定义,测试阶段需要沟通业务回归事宜,甚至上线都需要跨团队沟通应用的上线顺序。
		根据康威定律,团队的交流机制应与架构设计机制相对应。因此,在微服务架构下,职能团队的划分方法是我们首先要考虑的一个核心要素。
		微服务架构按照业务的功能进行划分,每个单一业务功能叫做一个服务,每个服务对应一个独立的职能团队,团队里面包含用户交互UI设计师,后台服务开发人员,
	DBA,运营和运维人员。
		在传统的整体架构中,软件是有生命周期的,经历需求分析,开发和测试,然后被交付给运维团队,这时开发团队将会解散,这是对软件的一个"放手"。而在微服务
	架构中,提倡运维人员也是服务项目团队的一员,倡导谁开发,谁维护,实施终生维护制度。
		在业务服务的内部实现需要升级或者变更时,团队内的各角色成员进行沟通即可,而不需要进行跨团队的沟通,这大大提高了沟通效率,只有服务之间的接口需要
	变更时,才需要跨部门沟通,如果前期在服务之间的交互定义上定义了良好的接口,则接口变更的概率不大。即使接口有变,也可以通过一定的设计模式和规范来解决。

	1.3.2 微服务的去中心化治理 
		微服务倡导去中心化的治理,不推荐每个微服务都要使用相同的标准和技术来开发和使用服务。对于异构系统之间的交互标准,通常可以使用工具来补偿。开发者可以
	开发共同的工具,并分享给异构系统的开发者,来解决异构系统的不一致问题。微服务倡导去中心化的服务管理和治理,尽量不要设置中心化的管理服务,最差也需要在中
	心化的管理服务宕机时有替代方案和设计。

	1.3.3 微服务的交互模式 
		1.读者容错模式
			读者容错模式指微服务化中服务提供者和消费者之间如何对接口的改变进行容错。从字面上来说,消费者需要对提供者提供的功能进行兼容性设计,尤其对
		服务提供者返回的内容进行兼容,或者解决在服务提供者改变接口或者数据的格式的情况下,如何让服务消费者正常运行。
			任何一个产品在设计时都无法预见将来可能增加的所有需求,服务的开发者通常通过迭代及时的增加新功能,或者让服务提供的api自然的演进。不过,服务
		提供者对外提供的接口的数据格式的改变,增加和删除,都会导致服务的消费者不能正常的工作。因此,在服务消费者处理服务提供者的消息过程中,需要对服务
		返回的消息进行过滤,只提取自己需要的内容,对多余或者未知的内容采取抛弃的策略,而不是硬生生的抛错处理。在实现过程中不推荐使用严格的校验策略,而是
		使用宽松的校验策略,即使服务消费者拿到的消息报文发生了改变,程序也只需要尽最大努力提取需要的数据,同时忽略不可识别的数据。只有在服务消费者完全不能
		识别接收到的消息,或者无法通过识别的信息继续处理流程时,才抛出异常。
			服务的消费者的容错模式忽略了新的消息项,可选的消息项,未知的数据值及服务消费者不需要的数据项。

		2.消费者驱动契约模式
			消费者驱动契约模式用来定义服务化中服务之间交互接口改变的最佳规则。

			服务契约分为:提供者契约,消费者契约及消费者驱动的契约,它从期望与约束的角度描述了服务提供者与服务消费者之间的联动关系。
			1.提供者契约
				是我们最常见的一种服务契约,顾名思义,提供者契约是以提供者为中心的,提供者提供了什么功能和消息格式,各消费者都会无条件的遵守这些约定,
			不论消费者实际需要多少功能,消费者接受了提供者契约时,都会根据服务提供者的规则来使用服务。

			2.消费者契约
				是对某个消费者的需求进行更为精确的描述,在一次具体的服务交互场景下,代表消费者需要提供者提供的功能中的哪部分数据。消费者契约可以被用来
			标识现有的提供者契约,也可以用来发现一个尚未明确的提供者契约。

			3.消费者驱动的契约
				代表服务提供者向其所有当前消费者承若遵守的约束。一旦各消费者把自己的具体期望告知提供者,则提供者无论在什么时间和场景下,都不应该打破契约。

			在现实的服务交互设计中,上面这三种契约是同时存在的。

			服务提供者契约是服务提供者单方面定下的规则,而一个消费者契约会成为提供者契约的一部分,多个服务消费者可以对服务提供者提出约束,服务提供者需要在
		将来遵守服务消费者提出的契约,这就是消费者驱动的契约。

		3.去数据共享模式
			与soa服务化对比,微服务是去 ESB 总线,去中心化及分布式的;而soa 还是以 ESB 为核心实现遗留系统的集成,以及基于 web service 为标准实现的通用
		的面向服务的架构。在微服务领域,微服务之间的交互通过定义良好的接口来实现,不允许使用共享数据来实现。
			在实践过程中,有些方案的设计使用缓存或者数据库作为两个服务之间的纽带。这种交互流程的缺点如下:
				1.使得微服务之间的交互除了接口契约,还存在数据存储契约
				2.上游的数据格式发生变化,可能导致下游的处理逻辑出现问题
				3.多个服务共享一个资源服务,对资源服务的运维难以划清职责和界限
				4.在做双机房独立部署时,需要考虑服务的资源的路由情况,跨机房的服务调用不能使用独立的资源部署模式,因此难以实现服务自治

			因此,在设计微服务架构时,一定不要共享缓存和数据库等资源,也不要使用总线模式,服务之间的通信和交互只能依赖定义良好的接口,通常使用restful样式
		的api 或者透明的RPC 调用框架。

	1.3.4 微服务的分解和组合模式
		使用微服务架构划分服务和团队是微服务架构实施的重要一步,良好的划分和拆分使系统达到松耦合和高内聚的效果,然后通过微服务的灵活组装可以满足上层的各种
	个样的业务处理需求。在微服务架构的需求分析和架构设计过程中,通常是用领域的动词和名词来划分微服务的。例如,对于一个电商后台系统,可以分解为订单,商品,
	商品目录,库存,购物车等子系统,每个名词和动词都可以是一个微服务,将这几个微服务组合在一起,就实现了电商平台用户购买商品的整个业务流。

		这样拆分以后,系统具有敏捷性,灵活性,可伸缩性等,拆分后有多个高度自治的微服务,以什么方式组合微服务呢?
		1.服务代理模式
			服务代理模式是最简单的服务组合模式,它根据业务的需求选择调用后端的某个服务。在返回给使用端之前,代理可以对后端服务的输出进行加工,也可以直接把
		后端服务的返回结果返回给使用端。	
			典型会使用到这种模式的是平滑的系统迁移,通常会经历如下4个阶段:
				1.在新老系统上双写
				2.迁移双写之前的历史遗留数据
				3.将读请求切换到新系统
				4.下调双写逻辑,只写新系统
			服务代理模式常常应用到第三步,一般会对读请求切换设计一个开关,在开关打开时查询新系统,开关关闭时查询老系统。

		2.服务聚合模式
			服务聚合模式是最常用的服务组合模式,它根据业务流程处理的需求,以一定的顺序调用依赖的多个微服务,对依赖的微服务返回的数据进行组合,加工和转换,
		最后以一定的形式返回给使用方。	
			这里体现了 DRY原则的设计理念,在设计或者构造应用时,最大限度的重用了现有的实现。假如一块业务逻辑由三个独立的逻辑块组成,每个独立的逻辑块可能
		有多个使用方,则DRY原则推荐将三个独立的逻辑块封装成三个独立运行的微服务,然后使用本节的服务聚合模式开发聚合服务,将三个独立的逻辑块聚合在一起提供
		给上层组合服务。好处如下:
			1.三个独立的子服务可以各自独立的开发,敏捷变更和部署
			2.聚合服务封装下层的业务处理服务,由三个独立的子服务完成数据持久化等工作,项目结构清晰明了
			3.三个独立的子服务对其他使用方仍然可以重用

			另外,聚合服务也可以是一个纯后台服务,通过聚合对使用方输出组合的服务。

		3.服务串联模式
			服务串联模式类似于一个工作流。
			服务串联模式之间的调用通常使用同步的restful风格的远程调用实现,注意,这种模式采用的是同步调用的方式,在串联服务没有完成并返回之前,所有的服务
		都会阻塞和等待,一个请求会占用一个线程来处理,因此在这种模式下不建议服务层级太多,如果能用服务聚合代替,则优先使用服务聚合模式,而不是使用这种服务
		串联模式。	
			相对于服务聚合模式,服务串联模式有一个优点,即串联链路上再增加一个节点时,只要不是在串联服务的正后面增加,那么串联服务是无感知的。

		4.服务分支模式
			服务分支模式是服务代理模式,服务聚合模式和服务串联模式相结合的产物。
			分支服务可以拥有自己的数据库存储,调用多个后端的服务或者服务串联链,然后将结果进行组合处理再返回给客户端。分支服务也可以使用代理模式,简单的
		调用后端的某个服务或者服务链,然后将返回的数据直接返回给使用方。

			由于分支模式放大了服务的依赖关系,因此在现实的微服务设计中尽量保持服务调用级别的简单,在使用服务组合和服务代理模式时,不要使用服务串联模式和
		服务分支模式,以保持服务依赖关系的清晰明了,也减少了日后维护的工作量。

		5.服务异步消息模式
			前面的所有服务组合模式都使用同步的restful风格的同步调用来实现,同步调用模式在调用的过程中会阻塞线程。如果服务提供方迟迟没有发挥,则服务消费方
		会一直阻塞,在严重情况下,出现雪崩效应。因此,在构建微服务架构系统时,通常会梳理核心系统的最小化服务集合,这些核心的系统服务使用同步调用,而其他
		核心链路意外的服务可以使用异步消息队列进行异步化。

		6.服务共享数据模式
			数据共享模式其实是反模式,由于去掉了数据共享,所以仅仅通过服务之间良好的定义的接口进行交互和通信,使得每个服务都是自治的。然后,在下面两种场景下,
		我们仍然需要数据共享模式。
			1.单元化架构
				由于一些平台对性能有较高的要求,所以采用微服务化将服务进行拆分,通过网络服务进行通信,尽管网络通信的带宽已经很宽,但是还是会有性能方面的损耗,
			在这种场景下,可以让不同的微服务共享一些自由,例如:缓存,数据库等,甚至可以将缓存和数据在物理拓扑上虞微服务部署在一个物理机房中,最大限度的减少
			网络通信带来的性能损耗,我们将这种方法称为"单元化架构"。

			2.遗留的整体服务
				对于历史遗留的传统单体服务,我们在重构微服务的过程中,发现单体服务依赖的数据库表耦合在一起,对其拆分需要进行反规范化的处理,可能会造成数据
			一致性问题,在没有对齐完全理解和把握的前提下,会选择保持现状,让不同的微服务暂时共享数据存储。

	1.3.5 微服务的容错模式 
		由于服务的调用不再是进程内的调用,而是通过网络进行的远程调用,众所周知,网络通信是不稳定,不可靠,一个服务依赖的服务可能出错,超时或者宕机,如果短时间
	没有及时发现和隔离问题,或者在设计中没有考虑如何应对这样的问题,那么很可能在短时间内服务的线程池中的线程被用满,资源耗尽,导致出现雪崩的情况。
		
		1.舱壁隔离模式
			微服务架构中主要体现如下2个方面:
				1.微服务容器分组
					微服务的每个节点的服务池分为三组:准生产环境,灰度环境和生产环境。准生产环境供内测使用;灰度环境会跑一些普通商户的流量‘大部分生产流量
				和VIP商户的流量则跑在生产环境中。这样,在一次比较大的重构过程中,我们就可以充分利用灰度环境的隔离性进行预验证,用普通商户的流量验证重构没有
				问题,再上生产环境。

				2.线程池隔离
					在微服务架构中,我们不一定将每个服务拆分到微小的粒度,这取决于职能团队和财务情况,我们一般会将同一功能划分在一个服务中,尽量避免微服务
				过细而导致成本增加,适可而止。这样就会导致多个功能混合部署在一个微服务实例中,这些微服务的不同功能通常使用一个线程池,导致一个功能流量增加
				时耗尽线程池的线程,而阻塞其他功能的服务。

		2.熔断模式
			当服务的输入负载迅速增加时,如果没有有效的措施对负载进行熔断,则会使服务迅速被压垮,服务被压垮会导致依赖的服务都被压垮,出现雪崩效应。因此,要在
		微服务中实现熔断模式。

		3.限流模式
			服务的容量和性能是有限的。针对服务突然上量,我们必须有限流机制,限流机制一般会控制访问的并发量。有如下几种主流的方法实现限流:
				1.计数器
				2.令牌筒
				3.信号量
				4.失效转移模式	
					若服务架构中发生了熔断和限流,则该如何处理被拒绝的请求呢?解决这个问题的模式叫做失效转移模式,通常分为下面几种:
						1.采用快速失败的策略,直接返回使用方错误,让使用方知道发生了问题并自行决定后续处理
						2.是否有备份服务,如果有备份服务,则迅速切换到备份服务
						3.失败的服务有可能是某台机器有问题,而不是所有的机器都有问题。例如OOM问题,在这种情况下适合使用 failover策略,采用重试的方法来
						解决,但是这种方法要求服务提供者的服务实现了幂等性。

	1.3.6 微服务的粒度 
		按照服务的初衷,服务要求按照业务的功能进行拆分,直到每个服务的功能和职责单一,甚至不可再拆分为止,以至于每个服务都能独立部署,扩容和缩容都很方便,
	能够有效的提高利用率。拆的越细,服务的耦合度越小,内聚性越好,越适合敏捷发布和上线。
		然后拆的太细会导致系统的服务数量较多,互相依赖的关系较为复杂,更重要的是根据康威定律,团队要响应系统的架构,每个微服务都有相应的独立,自治的团队来
	维护,这也是不切实际的想法。
		因此,这里倡导对微服务的拆分适可而止,原则是拆分到可以让使用方自由的编排底层的子服务来获得相应的组合服务即可,同时要考虑团队的建设及人员的数量和分配等。


1.4 Java平台微服务架构的项目组织形式 
	1.4.1 微服务项目的依赖关系 
		在java领域,每个服务上线后,对外输出的接口为一个jar包。在微服务领域,jar包被分为一方库,二方库,三方库。
			1.一方库:本服务在jvm进程内依赖的jar包
			2.二方库:在服务外通过网络通信或者rpc调用的服务的jar包
			3.三方库:所依赖的其他公司或者组织提供的服务或者模块

	1.4.2 微服务项目的层级结构 
		java微服务项目的层级结构一般为:服务导出层,接口层和逻辑实现层。
			服务导出层(War)
				web.xml
				Spring 环境

			服务接口层(Jar)
				业务接口
				DTO
				枚举类

			服务实现层(Jar)
				业务实现类
				外部服务包装类
				DAO

		其中,每一个层级的职责和最终的表现形式如下:
			1.服务导出层:最后会打包为一个War包,包含服务的实现Jar包,接口Jar包,以及web项目导出rpc服务所需要的配置文件等
			2.服务接口层:包含业务接口,依赖的DTO及需要的枚举类等,最后打包成Jar包,并发布到Maven服务器上,也包含在服务导出层的War包中。
			3.服务实现层:包含业务逻辑实现类,依赖的第三方服务的包装类,以及下层数据库访问的DAO类等,最后打包成Jar包,包含在服务到沪层的War包中。

		这里有一个反模式,切记永远不要在本地事务中调用远程服务,在这种场景下如果远程服务出现了问题,则会拖长事务,导致应用服务器占用太多的数据库连接,
	让服务器负载迅速攀升,在严重情况下会压垮数据库。虽然我们要极力避免这种场景的发生,但是数据库也应该要有熔断机制。

	1.4.3 微服务项目的持续发布 
		微服务项目需要实现自动化的持续部署和持续集成的功能,包括:代码管理,自动编译,发布QA,自动化测试,性能测试,准生产部署和测试,生产环境发布等。

1.5 服务化管理和治理框架的技术选型 
	1.5.1 RPC 
		1.JDK RMI
			自从 jdk 1.4 开始,jdk 内置了远程服务调用的技术栈,可以帮助开发者创建基于java到java的分布式调用框架,一个java进程内的服务可以调用其他java
		进程内的服务,使用jdk内置的序列化和反序列化协议。RMI 是 JEE 规范中 EJB 远程调用的基础。然后,jdk 内置的 RMI 服务并没有得到广泛的应用,原因如下:
			1.RMI 采用 jdk 自带的专用序列胡协议,不能跨语言
			2.使用了底层的网络协议,不如基于http可读,也不如http被广泛认可和应用
			3.开源框架的飞速发展,严重削弱了jdk资深技术的流程程度

		2.Hessian 及 Burlap
			Hessian 及 Burlap 都适合传输较小的对象,对较大,复杂的对象,无论是序列法方式上还是传输通道上都没有 RMI 有优势。由于服务框架中大量的调用
		都是大规模,高并发的短小请求,因此,Hessian 和 Burlap 协议爱服务化框架中得到了广泛的使用。

		3.Spring HTTP Invoker
			使用了jdk 内置的序列化机制,不能跨语言。

	1.5.2 服务化 
		服务化框架和平台:
			1.Dubbo
			2.HSF
			3.Thrif
			4.AXIS
			5.Mule ESB

	1.5.3 微服务 
		近年流行的 Spring Cloud 系列的微服务框架。

		1.Spring Boot
			通过使用 Spring Boot 可以很容易的创建独立的,具有高品质的基于 Spring 的应用程序,基于 Spring Boot 创建的应用可以随时随地的启动和运行,
		一般只需要较少的配置和搭建环境的工作量。
			在JEE时代,企业级开发涉及的通用功能被提取到了容器层实现,例如:tomcat web 容器负责管理服务的启动,停止,监控,配置和日志等,应用开发人员
		只需要按照规范将应用打包成War,并发布到tomcat web 容器中,就可以对外提供服务了,这一时代的应用是包含在容器内的。

			Spring Boot 的思路正好相反,它将容器嵌入自启动的jar包中,在Spring Boot应用启动时,内部启动嵌入的容器,例如:tomcat,Jetty和Netty等,
		然后通过内嵌的服务器将应用中提供的服务暴露。
			Spring Boot 这种设计在微服务架构下有如下明显的优点:
				1.可以创建独立,自启动的应用程序
				2.不需要构建War包并发布到容器中,构建和维护War包,容器的配置和管理也是需要成本的
				3.通过 Maven 的定制化标签,可以快速的创建 Spring Boot 的应用程序
				4.可以最大化的自动化的配置Spring,而不需要人工配置各项参数
				5.提供了产品化特点,例如:性能分析,健康检查和外部化配置
				6.全程没有xml配置,也不需要代码生成

			Spring Boot 是 Spring Cloud 构建微服务架构的重要基础。

		2.Netflix
			Netflix 是由 Netflix 公司开发且合并到 Spring Cloud 项目中,主要提供了服务发现,断路器和监控,智能路由,客户端负载均衡,易用的REST客户端
		等服务化必须的功能。其中 Hystrix 框架提供了微服务所需的容错机制的解决方案和设计模式。Hystrix 大大简化了微服务下容错机制的实现,包括服务分组和
		隔离,熔断和防止级联失败,限流机制,失效转移机制和监控机制等。

		3.Spring Cloud Netflix
			Spring Cloud Netflix 集成了 Spring Boot 对微服务敏捷启动和发布的功能,以及 Netflix 提供的微服务化管理和治理能力,称为一个完美的微服务
		解决方案。在 Spring Cloud Netflix 平台下,开发人员通过几个简单的注释配置即可完成一个大规模分布式系统的发布工作。Spring Cloud Netflix 包括
		服务发现组件 Eureka,容错性组件 Hystrix,智能路由组件Zuul 和客户端负载均衡组件 Ribbon。

			我们看到 Netflix 中的交互流程如下:
				1.服务在 Eureka 服务器实例上注册
				2.Zuul 作为一个特殊的服务在 Eureka 上注册并发现服务
				3.Zuul 作为网关,将发现的服务导出给pc网站,app 和 开放平台使用
				4.RestTemplace 和 FeignClient 使用简单的服务调用的方法调用服务1,服务2等

			在这个微服务的使用流程中,Netflix 具有如下特点:
				1.服务在 Eureka 实例中注册,由Spring 管理的Bean来发现和调用
				2.通过配置的方式可以启动嵌入式的 Eureka 服务器
				3.Feign 客户端通过声明的方式即可导入服务代理
				4.Zuul 使用 Ribbon 服务实现客户端的负载均衡
				5.通过声明的方式即可插入 Hystrix 的客户端
				6.通过配置的方式即可启动 Hystrix 面板服务器
				7.在Spring 环境中可以直接配置 Netflix 的组件
				8.Zuul 可以自动注册过滤器和路由器,形成一个反向代理服务器
				9.Hystrix 面板可以对服务的状态进行监控,并能提供了容错机制


1.6 本章小结
	微服务架构的主要特点:
		1.将传统单体应用拆分成网络服务,来实现模块化组件
		2.根据微服务架构的服务划分来分组职能团队,减少跨团队的沟通
		3.每个服务对应一个团队,团队成员负责开发,测试,运维和运营,开发后在团队内运维和运营,不需要交付给其他团队
		4.去中心化,去SOA服务化的中心服务治理和去企业服务总线
		5.微服务重视服务的合理拆分,分层和构造,可建设自动化持续发布平台,并进行敏捷开发和部署
		6.具备兼容性,容错性设计和服务的契约设计

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
分布式服务架构:原理设计实战pdf》是一本介绍分布式服务架构的书籍,以下是我对这本书的回答。 这本书是关于分布式服务架构原理设计实战的指南。分布式服务架构是一种软件架构模式,它通过将一个应用程序分解为多个独立的服务来处理不同的业务逻辑。每个服务都可以独立部署、扩展和管理,通过网络进行通信和协作。 在这本书中,作者首先介绍了分布式服务架构的基本原理和概念。他们解释了为什么分布式服务架构在现代软件开发中如此重要,以及如何将其与传统的单体应用程序架构进行对比。接着,他们详细讨论了设计分布式服务架构的一些关键问题,如服务的边界划分、通信机制、数据一致性和容错机制等。同时,他们还介绍了一些常用的分布式服务框架和工具,如Dubbo、Spring Cloud和Kubernetes等。 在实战部分,作者提供了一些实际案例和应用场景,展示了如何应用分布式服务架构来解决现实世界中的问题。他们从不同的角度和维度分析了这些案例,包括性能优化、系统可用性、弹性伸缩和容灾等。通过这些案例,读者可以更好地理解和应用分布式服务架构。 总的来说,这本书在分布式服务架构原理设计实战方面提供了全面的指导。无论是对于初学者还是有一定经验的开发人员来说,这本书都是一个宝贵的参考资料。它不仅介绍了基本原理和关键概念,还提供了一些实际的案例和经验教训。通过阅读这本书,读者可以更好地理解和应用分布式服务架构,从而提高软件开发的效率和质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值