一文带你搞懂微服务架构深度解析:微服务的采用前提,技术与理念

技术与理念

微服务的概念还在快速发展的过程中,它不仅给我们提供了分布式下细粒度服务设计、构建、交付、运维的方法,同时整合了过去几年行业的先进技术和最佳实践。

面向服务

大部分企业选择微服务架构是业务驱动的。对于基于传统J2EE技术栈的Web项目而言,早期单体架构就是所谓的“一个War包打天下”,将应用程序的所有功能都打包成一个独立的War包,部署在Tomcat的指定目录下就可以顺利运行。然而,软件项目是一个不断迭代和变化的过程,业务模块的增加、功能的扩展、人员的更迭、需求的变动最终都需要修改代码来实现。于是代码跟随版本的不断升级而逐渐膨胀变得难以维护。单体架构的灵活性、可扩展性、可运维性都明显下降,开发人员效率降低、系统稳定性变差、局部小问题导致“牵一发而动全身”。

在这种情况下,单体架构为了保证程序内部的高内聚、低耦合,引入了分层的架构模式。分层架构在某种程度上解决了不同类型代码的逻辑耦合问题,模块之间有了更加清晰的职责划分,降低了单体架构的整体复杂度。而分层架构的问题是没有聚焦当前业务逻辑,以技术为导向的架构形态很难做到服务的复用,业务模块无法独立部署和演进。

微服务的理念与SOA服务架构是一脉相承的,微服务架构同样强调面向服务,将一个大的“问题空间”通过领域建模拆解分为实体之间的关系和行为,使用限界上下文(Bounded Context)将实现细节封装起来,让服务可以独立伸缩,每个服务都有明确的边界。

在面向业务构建微服务时,我们不应该把主要的关注点放在是采用 Tomcat 还 是 Jetty 应 用 容 器 上 , 也 不 应 该 放 在 Spring Cloud 、Docker、RPC这些技术概念或框架上。微服务架构首先要考虑的是解决业务的问题。在开始微服务架构转型之前,请先理解业务,洞察业务边界、职责划分,让团队专注于实现某个特定的应用服务。微服务需要根据一定的软件设计原则来实现面向服务的架构模式,本文在微服务构建章节会深入讲解领域驱动设计如何帮助我们对系统进行合理的服务划分,如何拆解、聚合以实现服务的开发和复用。另外,面向服务的系统的服务边界划分需要我们格外注意,因为错误的服务领域划分将会使服务陷入大量的远程调用和分布式事务中,在这种情况下,微服务给整个系统带来的不是便利而是麻烦。

底座技术

从效率的角度出发,微服务架构需要配套的技术栈和技术底座支撑。目前,很多一线互联网公司已经成功基于底座技术实现了微服务架构的落地和实践。

技术选型是落地微服务架构的关键环节,公司在落地微服务架构的过程中,不仅仅要关注技术本身,更重要的是结合自己公司的技术现状和人员技术背景,根据已有的技术栈来进行微服务架构的落地和实践。

从技术选型的角度出发,我们需要根据一定的优先级来考虑:需求满足度、社区活跃度、技术掌控能力。

● “需求满足度”是最重要的因素,因为技术和架构最根本的动机还是满足业务的需求,如果一项先进的技术没有满足用户的需求,则这项技术将失去发展的动力。

● “社区的活跃度”是非常重要的参考,因为社区的活跃度代表了这项技术被广大开发者接受的程度和这项技术的广泛度和生命力。对于技术薄弱的公司,最好采用在一线互联网公司落地并且在社区内拥有良好口碑的开源产品。因为这些技术已经在大企业中经过了生产环境的验证,并且有良好的社区生态,可以得到更多的技术支持。当然,有实力的公司会选择通过自研的方式落地微服务架构,而对于小规模团队,还是建议采用社区的技术框架落地微服务架构,一方面可以不用从头开始,另一方面,也会降低公司的整体学习成本。

● 同时,需要考虑公司人员的技术掌控能力。例如,如果一个框架使用C语言实现了微服务架构,虽然在性能上有优势,但整个团队没有懂C语言的开发者,那么就需要重新考虑是否有其他的替代技术方案。

基于Spring社区的影响力,目前可以认为Spring Boot是构建Java微服务架构的事实标准;另外,Dubbo是阿里多年的生产级分布式微服务实践的技术结晶,Dubbo本质上是一套基于Java的RPC框架,服务治理能力非常强,在国内技术社区中具有很大的影响力。还有ApacheServiceComb等国内外知名微服务框架,这里就不再赘述。

架构技术

单体架构被拆分为微服务后,需要解决众多服务的治理及复杂度管控问题。微服务存在领域模型建设、服务边界划分、服务与服务之间的依赖、服务交互集成、独立数据管理等问题,针对这些,我们需要优化我们的架构设计理念和设计方法。

领域驱动设计

Eric Evans在《领域驱动设计》一书中对不同公司的业务应用程序中遇到的复杂问题进行了总结,帮助我们在现实世界中进行建模。

他为领域驱动设计提出了大量的最佳实践和经验技巧:

● 领域驱动设计方法有利于软件开发团队与业务部门或领域专家密切合作,使开发人员与业务人员达成共识。

● 技术人员和业务专家应该首先进行领域建模,找到有界的上下文和相关的核心域,以及普遍存在的语言、子域、上下文映射,用于简化软件项目的复杂度,使得设计思路能够更加清晰、设计过程更加规范。

对于微服务架构而言,它和领域驱动设计同样关注业务。领域驱动设计理念聚焦于领域建模、实体、边界划分、界限上下文。领域驱动设计非常适合从业务上去划分微服务的边界,定义服务对外暴露的接口。每一个微服务都应该是一个可以独立开发、部署、运行的自治主体。可以说,领域驱动设计是指导微服务架构设计、解耦业务、服务拆分、服务构建的关键原则。

前后端分离技术

微服务倡导专业分工,每个组件都专注于各自的业务领域。而大部分软件,尤其是面向企业领域的系统基本都是由前端和后端服务组成的。将前后端分离作为切入点,我们可以轻松地开启微服务化改造之旅。下面是微服务架构进行前后端职责划分的主要规则:

● 技能分离,前后端可以使用不同的特定语言或框架来实现最佳的微服务实践。

● 职责分离,前端主要负责和用户的交互逻辑,后端主要负责业务逻辑和资源的管理。

● 部署分离,前端和后端可以做到独立发布,不存在发布过程的耦合,前端和后端可以根据约定的API进行版本迭代和独立演进。

前后端分离架构有利于将微服务在技术层面上解耦,后端微服务可以专注于实现对后端服务和资源的管理,而不用再关注与用户交互的逻辑验证等问题。

前后端分离有利于微服务中的各组件的演进和组合,微服务架构细粒度的服务可以让不同前端共享不同后端,通过“搭积木”的方式实现服务的复用和独立的演进,如下图所示。

事件驱动技术

在单体架构下,系统的复杂性在于如何做好模块之间的解耦,因为模块依然存在于同一个进程中,实现进程内的并发处理和多线程模型的管理是单体架构的主要工作。所以单体架构的瓶颈往往是CPU,不适合网络I/O密集型的计算处理场景。而在微服务架构下,因为细粒度的服务之间的交互主要通过分布式网络进行,而事件驱动架构为微服务提供了更多的跨网络集成优势。

● 基于事件的体系结构是异步的,不存在网络阻塞。在提供服务之前,我们必须考虑网络的局限性。选择REST同步调用方式存在服务调用依赖问题,会产生级联消息雪崩效应,而选择事件机制我们不用担心同步调用的问题。

● 基于消息队列的异步消息处理机制。相比请求/响应模式的服务集成方式,采用Broker代理的服务集成方式可实现服务之间的解耦,同时可以提高服务的性能、可靠性、可扩展性。

然而,事件驱动框架也会在消息一致性、消息的监控和传输上给系统带来额外的技术复杂性。

● “协同”优先“编排”原则。事件编排机制会由“中心大脑”

来领导并驱动整个流程,这个大脑就像交响乐队中的指挥;事件协同机制会预先说明清楚系统中各个部件的职责,而把具体怎么实现留给各个部件。总的来说,事件编排机制的缺点是明显的,中心控制点承担了太多职责,它会成为网状结构的中心枢纽。而事件协同机制不仅可以降低系统的耦合性,还可以让我们以更加灵活的方式修改现有系统。

● CQRS(Command and Query Responsibly Separate,命令查询职责分离),是介于脚本驱动和领取驱动之间的一种服务建模与数据交互模式,是事件驱动领域中被广泛使用的一个概念,通过CQRS可以解决数据读写交叉问题,并能有效降低业务逻辑的复杂性。

服务监控与治理

在单体架构时代,因为所有服务都集中在少数几个系统中,系统之间的相互调用关系相对简单,在出现故障时,可以将问题根源锁定在有限的系统范围内并定位问题。而在微服务架构下,众多微服务实例之间有频繁的分布式跨网络协作、相互远程调用,这时如果没有一整套服务治理方法,帮助我们保证SLA(Service-Level Agreement,服务等级协议)、增强服务治理水平、提升微服务的治理与运维效率,那么微服务的转型之路将举步维艰。

技术团队关注的焦点往往是架构的实现和业务建模,容易忽略微服务架构带来的一系列负面影响,通过微服务监控与治理可以全方位地掌控当前服务的运行状态和资源利用情况,可以说,服务治理与监控既是微服务架构在平台层面的核心工作,也是微服务应用“长治久安”的前提。通过微服务治理能力的提升,可以提供对业务应用的快速响应能力、保证业务的健康稳定及持续演进;在技术上,可以帮助微服务的开发和运维人员实时地掌握微服务的运行状态,以及进行问题定位和故障恢复。

在服务治理的技术选型上,Spring Cloud提供了服务治理的一站式解决方案。同时,微服务框架结合众多技术组件可以提供Metrics指标监控、日志监控、调用链等信息监控、健康检查和告警通知等功能。Metrics监控主要依赖于时间序列数据库,目前较成熟的产品有Prometheus 和 OpenTSDB; 我 们 可 以 采 用 ELK ( Elasticsearch 、Logstash、Kibana三个技术框架缩写)技术栈实现日志的归集、存储、搜索和可视化报表查看等;可以采用Spring Cloud Sleuth日志收集工具包,结合Zipkin和HTrace,作为Spring Cloud的一种分布式追踪解决方案。

容器和自动化技术

容器和自动化技术可以说是微服务规模化发展需要解决的首要问题。基于容器的部署和交付无论在软件开发领域,还是运维相关领域,都带来了巨大的技术颠覆。通过自动化交付部署可以将开发与运维环节打通。交付物的标准化使得我们可以“标准化”地交付应用及它所依赖的运行环境。Docker容器一次构建、多次交付的特性可以使微服务具备了更好的可移植性、可复用性。

很多人把容器化和微服务架构混为一谈,认为自己的服务部署到了容器后,系统就是一个微服务架构了。其实二者存在本质上的差异。可以说,一个巨石型单体架构即使部署到了容器上,依然无法改变它架构上的“拙劣”。

目前容器技术仍然是微服务架构最佳的运行时环境和平台,也很好地支撑了微服务架构去中心化、细粒度、容错、伸缩的特性。如下图所示,是虚拟机与容器不同的隔离机制。

虚拟机

容器

使用传统虚拟机的应用存在如下运维弊端:

● 部署非常慢、成本非常高、资源浪费。

● 难以迁移和扩展。

● 服务与硬件厂商提供的特性绑定。

使用容器对微服务架构进行自动化运维的优势:

● 容器的资源开销更小,Docker本身共享操作系统内核,容器可以节省更多物理机资源。

● 在开发和运维之间搭建了一座桥梁,是实现DevOps的最佳方案。

● 容器可以对软件和其依赖的标准镜像格式打包,保证应用在不同运行环境下的统一交付,解决环境差异问题和大规模的交付部署问题。

● 容器本质上相当于一个进程,每个容器都可以看作一个不同的微服务进程,因此可以独立升级,与底层共享操作系统,性能更加优良,系统负载更低,在同等硬件资源条件下可以运行更多的应用实例,更充分地利用系统资源。

● 在没有适合的工具和自动化运维的情况下,使用微服务架构会导致灾难。目前基于容器技术和Kubernetes技术的平台已经成为微服务交付和管理的最佳平台。

云原生12要素

Gartner定期发布的技术成熟度曲线可以帮助我们方便地评估技术的成熟度,同时帮助我们制定战略,即采用怎样的技术工具。Gartner最新发布的技术影响力和普及模式与成熟度分析说明,微服务架构已经在中国全面进入成熟落地阶段,从全球来讲,很多知名IT企业和公司,像亚马逊、Netflix、阿里巴巴,已经采用微服务架构重塑了自己的核心业务系统。当前,很多公司为了节省成本、减少对基础硬件设施的投入,纷纷选择采用公有云或者私有云的方式管理公司的应用服务和基础设施。

云原生12要素(如下图所示)是基于云的架构设计和开发模式需要具备的一套全新的理念,也是云原生应用开发的最佳实践原则。

● 要素1:基准代码

基准代码和应用之间总是保持一一对应的关系:一旦有多个基准代码,就不能称为一个应用,而是一个分布式系统。分布式系统中的每一个组件都是一个应用,每一个应用都可以分别使用云原生12要素进行开发。

● 要素2:依赖显式声明依赖关系,应用程序不会隐式依赖系统级的类库。要通过依赖清单,确切地声明所有依赖项。此外,在运行过程中通过依赖隔离工具来确保程序不会调用系统中存在但清单中未声明的依赖项。这一做***统一应用到生产和开发环境。像Java语言使用的Maven打包软件或者Cradle都可以显式声明依赖。

● 要素3:配置

通常应用的配置在不同部署环境(预发布、生产环境、开发环境等)中会有很大差异。Factor推荐将应用的配置存储于环境变量中。我们可以非常方便地在不同的部署环境中修改环境变量,却不动一行代码。

● 要素4:后端服务

这里的后端服务指的是应用运行所依赖的各种服务,例如数据库、消息代理、缓存系统等,对于云原生应用来说,往往还会有日志收集服务、对象存储服务及各种通过API访问的服务,可以把这些服务作为外部的、通过网络调用的资源。

● 要素5:构建、发布和运行

构建、发布和运行三个阶段需要有严格的界限,部署工具应该明确每个发布版本的唯一发布ID对应的构建版本。

● 要素6:进程

应用进程的内部不要保存状态信息,以一个或多个无状态的进程运行应用,任何状态信息都应该被保存在数据库、缓存系统等外部服务中。应用实例之间的数据共享也要通过数据库和缓存系统等外部服务进行,直接的数据共享不但违反无状态原则,还引入了串行化的单点,这会给应用的横向扩展带来障碍。

● 要素7:端口绑定

通过端口绑定提供服务,应用完全自我加载而不依赖于任何网络服务器就可以创建一个面向网络的服务。互联网应用通过端口绑定来提供服务,并监听发送至该端口的请求。

● 要素8:并发通过进程模型进行扩展,任何计算机程序一旦启动,就会生成一个或多个进程。互联网应用采用多种进程运行方式,而不是线程方式,进程是“一等公民”。

● 要素9:易处理

要求应用可以瞬间(理想情况下是数秒或者更短时间)启动或停止,因为快速启动和优雅终止可最大化程序的健壮性,这将有利于应用快速进行横向扩展和变更,或者进行故障后的重新部署,这两者都是程序健壮性的体现。

● 要素10:环境等价

环境等价的浅层次含义是要求在开发环境和线上环境中使用相同的软件栈,并尽可能为这些软件栈使用相同的配置,以避免程序对不同环境的依赖。

● 要素11:日志

应用程序应该将其产生的事件以每个事件一行的格式按时间顺序输出,这点毋庸置疑,但是本要素想说的其实是:应用程序不要自行管理日志文件。

● 要素12:管理进程

一次性管理进程应该和正常的常驻进程使用同样的环境。这些管理进程和任何其他的进程一样使用相同的代码和配置,基于某个发布版本运行。后台管理代码应该随其他应用程序代码一起发布,从而避免同步问题。屏蔽环境差异和集群下的多实例问题。

总之,云原生12要素很适合快速部署应用程序,因为它们不需要对将要部署的环境做任何假定。它允许底层云平台使用简单而一致的机制,轻松实现自动化,快速配置新环境并部署应用,同时实现规模优化、应用快速迭代演进。

全部评论

相关推荐

12-10 13:06
北京大学 Java
牛友们都收到开奖电话没
淳水微凉:骗人的,散了散了
点赞 评论 收藏
分享
牛客533433175号:更可气的是我做完这些给我拒了
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务