到底什么是服务治理?
栏目:行业动态 发布时间:2023-05-04
 完美体育首先需要明确,不管是什么事物需要”治理“,那一定是该事物存在一定问题。比如环境治理。那么服务,或者说微服务为什么需要治理?  对于服务来说,如果它承担的业务职责简单,那其实治理的必要性不大,因为服务运行过程是相对透明的,即使出现问题也能较快发现、定位、回滚。  当服务承担的业务职责变多变大,那随着更多问题的到来,服务治理开始变得必要。服务治理也与技术架构本身息息相关。  如果服务属于单

  完美体育首先需要明确,不管是什么事物需要”治理“,那一定是该事物存在一定问题。比如环境治理。那么服务,或者说微服务为什么需要治理?

  对于服务来说,如果它承担的业务职责简单,那其实治理的必要性不大,因为服务运行过程是相对透明的,即使出现问题也能较快发现、定位、回滚。

  当服务承担的业务职责变多变大,那随着更多问题的到来,服务治理开始变得必要。服务治理也与技术架构本身息息相关。

  如果服务属于单体结构,服务治理的挑战更多是当单体架构由于承载的业务庞大,服务内部逻辑变得复杂,扩展性也变差。这时候往往不需要特别的服务治理手段,而是将单体服务拆分为微服务,即完成”微服务化“,将原有单体服务架构向微服务架构演进。

  业务服务演进到微服务架构后,服务治理问题是否就此终结?远远没有。在微服务架构下,出现了新的服务问题,从而需要对微服务进行服务治理。那微服务又有哪些问题需要治理?

  1、服务注册与发现。单体服务拆分为微服务后,如果微服务之间存在调用依赖,就需要得到目标服务的服务地址,也就是微服务治理的”服务发现“。要完成服务发现,就需要将服务信息存储到某个载体,载体本身即是微服务治理的”服务注册中心“,而存储到载体的动作即是”服务注册“。

  2、可观测性。微服务由于较单体应用有了更多的部署载体,需要对众多服务间的调用关系、状态有清晰的掌控。可观测性就包括了调用拓扑关系、监控(Metrics)、日志(Logging)、调用追踪(Trace)等。

  3、流量管理。由于微服务本身存在不同版本,在版本更迭过程中,需要对微服务间调用进行控制,以完成微服务版本更迭的平滑。这一过程中需要根据流量的特征(访问参数等)、百分比向不同版本服务分发,这也孵化出灰度发布、蓝绿发布、A/B测试等服务治理的细分主题。

  4、安全。不同微服务承载自身独有的业务职责,对于业务敏感的微服务,需要对其他服务的访问进行认证与鉴权,也就是安全问题。

  5、控制。对服务治理能力充分建设后,就需要有足够的控制能力,能实时进行服务治理策略向微服务分发。

  而对于微服务治理,传统的做法都是需要引入微服务研发框架,配合控制平成如上服务治理能力的建设。比较常见的微服务研发框架包括SpringCloud、Dubbo等。

  讲到微服务框架本身,不妨多说一些。服务本身需要治理,其实传统微服务框架本身也存在一些问题,同样需要”治理“:

  3、多语言支持不足。SpringCloud、Dubbo都是Java语言主打框架,要想支持更多语言就变得十分困难

  服务网格是一个微服务基础设施,用于处理微服务通信、治理、控制、可观测、安全等问题,具备业务无侵入、多语言、热升级等诸多特性,是业界下一代微服务架构方向。

  目前业界较为主流的是Google、IBM、Lyft主导研发的Istio框架,当然也有一些基于Istio实现的易用性更强的平台(如网易轻舟Service Mesh,利益相关),对Service Mesh本身的易用性、可观察性、可运维性等有了进一步增强。可以说Service Mesh架构本身目前站在了服务治理领域的顶峰。

  我们帮助各行业客户数字化转型升级,成功实现业务增长。点击查看部分案例,解锁企业专属转型新思路:

  今天我准备再谈下微服务治理方面的内容,在前面我写过一篇微服务治理框架重构的文章,里面给出了一个完整的覆盖微服务全生命周期管理和后期治理管控的框架体系。今天的重点则是对里面的一些内容进行细化说明。

  对于微服务治理在前面已经谈到了实际上包括了微服务模块本身和微服务API接口治理两个方面的内容,而不能简单理解为API接口的治理。

  微服务治理是针对企业组织和业务目标,制订一套标准的管理,业务,技术,过程规范体系,实现微服务从需求,设计,开发上线,运行,下线的全生命周期管理能力。同时构建一套完整的度量指标体系,通过实时的日志和性能数据采集,持续的监控服务运行监控状态,并执行相应的限流,预警等管控策略,以确保微服务的持续健康,可靠和高效运行。

  以上就是一个微服务治理本书应该包括的全面内容。从这个里面也可以看到微服务治理平台或开发框架实际上仅仅占了微服务治理的一部分内容,而不是全部。

  上图给出的围绕微服务全生命周期管理和基于服务度量体系的持续运维监控两个方面展开,对于一些二级的内容在该图暂时无法展开,比如常说的服务版本管理,服务依赖分析也是微服务治理的关键内容,暂时在该图没有体现。

  在运行期还有一个关键思维的转变就是不是简单的发生问题故障后的运维治理,而是应该基于监控预警分析下的主动的技术运营和SLA服务等级提升。

  如果你要去给别人做微服务治理,实际上是客户在确定了微服务架构后就需要介入,包括选择什么样的开发框架,采用哪些开源技术,这些开源技术如何整合,微服务如何拆分,微服务开发过程如何规范化,如何持续集成和部署,API接口如何设计,微服务间如何集成,运行期微服务如何进行状态和性能监控,如何进行安全,日志,限流等管控。

  以上所有内容都应该纳入到微服务治理范畴。那么当前企业实施微服务都会去请技术咨询公司来进行完整的微服务治理规划和咨询吗?

  对于治理这件事,我最近也在思考。治理不是别人给你一套框架,一套标准规范体系你就能够使用得好的。治理这种事情最佳的方式更多应该是别人给你一个粗粒度的规则,然后你尽快去执行,在执行过程中通过短周期迭代不断的去自我优化和调整。

  也就是说一个组织治理过程的完善往往是问题驱动的自我不断完善,这个完善过程来源于实践。只有你自己吃亏了,走弯路或遇到问题了,你才真正理解为何要制定一个规则。

  一接触到微服务,实际上并不是马上谈到标准规范,也不是马上去谈后期的运维监控。更多的都是在谈前期的开发框架和开源组件的选择。

  因此你经常会看到究竟是选择SpringCLoud还是Dubbo,类似Eureka,Consul,Nacos这么多的开源注册中心实现究竟应该选择哪个;是选择SpringCLoud框架中的Zuul或CLoud Gateway微服务网关,还是选择类似Kong这种独立的API网关。服务限流是选择Hystrix还是Sentinel;对于后期监控运维,包括ELK方案,Prometheus,还是Skywalking;有无必要选择独立的Apollo来做服务配置中心?当前基于ServiceMesh服务网格的Istio微服务治理是否可以替代传统治理方案等。

  这个问题,我在前面也回答过。就是当你没有足够的实践经验积累的时候,最好的方法就是选择一个大而全的框架体系,然后根据需要来启用里面的一些关键组件和功能。

  可以看到这个框架里面类似服务注册和发现,限流熔断,安全,负载均衡,声明式调用,配置中心,微服务网关等都具备,你只要按需要选择使用即可。

  所以一开始切入微服务的时候,你不要去谈类似Nacos,Sentinel功能更加强大,Kong网关的性能更好这些。大部分组织刚切入到微服务的时候,很多高级功能你并不需要,一开始你的性能需求也没有到追求极致的程度。

  因此类似选择SpringCLoud完整框架体系,减少组件间的集成工作量,快速地搭建完成框架并进入到设计开发阶段才是重点。可以看到前面谈到的其它开源组件基本都是适配SpringCLoud微服务框架的,也就是说你后期再引入这些组件可以做到平滑过渡。

  对于SpingCLoud开源框架,实际上既包括了开发框架,也包括了治理框架,而且两者是耦合或集成在一起的。也就是说微服务在开发阶段,往往就需要考虑为了治理需求增加相应的配置文件,或在类文件或方法上面增加相应的声明式标注。

  所以你会看到如果你的限流策略要变化,往往并没有那么容易,涉及到代码或配置文件的修改才能够完成。

  而个人一直以来的一个重要观点就是微服务开发框架和微服务治理应该彻底解耦,在开发阶段不应该过多地去考虑治理能力,或者说为了治理能力增加相应的开发工作。包括前面谈到的后续主流的ServiceMesh微服务治理,基本也是基于这个无侵入原则进行。

  第二个经常会遇到的问题即是类似SpringCLoud已经有Config配置中心,为何还需要采用Apollo配置中心,或者说SpingCloud已经有了微服务网关,有无必要还去采用类似Kong这种API网关能力。包括Eureka注册中心和Nacos选择也是同样的问题。

  如果你仅仅是从性能,功能层面去思考那么往往就没有彻底理解。而真正你需要考虑的是站在一个大组织层面管理多个微服务应用,还是仅仅一个微服务应用内部开发管控层面。

  对于SpingCLoud完整框架方案,其核心定位还是在一个微服务应用开发团队层面,即一个传统单体应用拆分为了10个微服务开发,但是整体来说对外还是一个应用,由一个大的开发团队来开发和交付。这个开发团队本身在进行10个微服务间的集成,交互,安全等问题处理的时候需要一套完整的管控治理框架和方案。

  但是如果站在一个企业层面,往往存在多个这样的开发团队,不同的开发团队开发不同的微服务应用,同时采用的微服务开发框架都还可能不同。比如五个独立的应用开发团队,分别开发了SRM,CRM,MES等五个应用。

  那么组织层面面对的是这5个大的微服务应用如何进行管控治理。这个已经不再是单个微服务应用内部的事情,而是跨微服务间的事情。

  而当上升到跨微服务应用,管理多个微服务应用的时候,类似Nacos,Kong网关,Apollo配置中心才会起到关键的作用。这些管控治理不是由单个微服务应用开发团队来负责,而是应该是组织级的管控治理团队。

  当我们谈到微服务治理的时候,经常已经是面临一个无法解决的问题,比如说微服务拆分得太细,接口集成关系复杂难以管理,持续应用故障的时候难以快速的定位和排查等。

  当真正变成问题的时候你采用再好的链路监控工具,管控治理措施都是徒劳,并且已经无法从根本上解决问题。

  在我头条上,实际上我有多篇文章都在谈微服务如何拆分的话题。这些拆分方法基本是可以归结为两类方法。

  第一种方法是传统的基于企业架构规划的思路,梳理业务架构和数据架构,并通过业务功能和流程,业务功能和数据对象的多个CRUD分析矩阵来分析功能,数据之间的耦合性,完成最终的拆分工作。其本质还是传统的单体应用里的模块拆分,但是传统模块拆分不会考虑数据库DB层也要拆分,这个是微服务拆分带来的一个新要求。

  第二种方法则是基于领域建模分析的思路,去考虑上下文边界,去分析具体的业务功能和数据之间的耦合性完成拆分动作。这个拆分的核心并不是功能模块的拆分,而是功能模块对应的底层数据对象如何拆分。

  严格意义上的微服务,数据库也完全独立和解耦,这样会导致数据库拆分太细,引入后期大量的分布式事务处理和管理难度。

  因此更好的方法是划分业务域,不同业务域对应不同的数据库。可以多个微服务共享一个数据库。在多个微服务共享一个数据库实例的时候,微服务本身没有做到完全解耦,但是也可以实现代码层解耦。

  对应API接口识别,实际上微服务在设计阶段第二个重点,即如何保证识别的微服务足够的粗粒度和可复用。

  实际我们看到在实践过程中,很多项目团队的管理中心在微服务模块上,而没有在微服务模块暴露的API接口上,导致后续的接口集成混乱。

  第一个层面是单个微服务存在的后端模块和前端模块之间的接口,这类情况下往往后端暴露大量的API接口给前端调用,很多接口可能还是CRUD级别的细粒度接口。

  第二个层面是一个大应用里面,各个微服务模块之间的API接口,比如供应链管理应用中招投标管理微服务和采购微服务两者之间的API接口。这类接口跨微服务,不应该出现重度耦合的情况。

  第三个层面是大应用对外暴露的接口,比如供应链整个应用应该对外暴露和注册到外部API网关或能力开放平台,和ERP,和PMS等外部其他应用交互的接口。

  对于第一个层面往往是弱管控,类似通过JWT保证基本的安全即可。而对于第二和第三个层面的接口则应该强管控,即应该管控到每一个API接口这个粒度。比如招投标模块的后端暴露了30个API接口给前端用,但是并不是说采购微服务也能够任意访问这30个接口服务。同时接口应该是粗粒度的,可复用的,微服务之间,微服务应用之间不应该出现大量接互集成。如果出现,那么就说明两者耦合很紧,没有达到解耦的目的。

  如果我来指导微服务架构下的开发过程改进,那么一定会谈到API接口驱动这个核心思路。一个是微服务本身可能划分为了不同的团队在开发,一个是微服务本身又划分了前后端分离分为不同的角色在开发。

  如果API接口在前期都没有定义清楚就开始开发工作,那么后续集成一定会出问题。API接口规范或契约是前端开发,后端开发,测试人员共同遵循的一个关键内容。

  如上图,大家遵循同样的接口契约,那么后端开发,前端开发和测试人员可以并行开始各自的工作。对于前端优先进行接口开发和实现,前端则通过接口契约产生Mock模拟,通过接口模拟实现来进行前端功能的开发。在前后端开发过程中,测试人员也可以根据接口定义进行测试设计工作,同时进行相关的测试脚本设计或录制工作。

  在微服务架构实施过程中,一般都会谈到容器云和DevOps持续集成和交付。

  因此微服务治理过程中的运行态,更多的就是解决微服务如何和容器云资源集成的过程,包括了微服务整个编译,构建,部署和交付过程,如何通过DevOps思想来实现敏捷和自动化的过程。

  即微服务架构实施过程中,我们需要考虑微服务的设计开发和交付,一开始就是支撑全面上云的,能够部署和交付到云原生技术底座上面。

  微服务开发框架和环境,敏捷研发管理和工具,容器云PaaS平台三者之间的融合和集成。而整个融合和集成我们通过DevOps支撑平台来完成。

  如果这样的话DevOps平台可以看做是微服务开发和交付过程中重要的一个治理平台。

  一个微服务在设计阶段完成后,进入到开发和部署交付阶段,那么这个阶段重点就是进行DevOps过程实践,真正统一敏捷研发和持续集成交付过程。当DevOps完整实施下去后,你可以看到整个微服务开发交付过程自然就理顺了。

  那么实际上到了运维监控阶段,服务治理管控核心就三个方面的内容。其一是治理规则中心,其二是监控和度量中心,其三是管控执行中心。

  简单来说运维阶段的服务治理重点就是首先制定了服务治理规则,包括了安全规则,限流规则,服务SLA规则等。然后就是进行微服务运行日志,接口服务日志,资源性能日志等的数据采集和度量分析。当分析结果触发了规则后,那么就进行了相关的规则执行。

  规则执行则是最终具体的管控手段。规则执行将直线导致微服务运行状态的变化,微服务SLA等级的变化,资源层的变化等。

  当然监控和度量分析中心也可能没有直接触发规则的执行,而是我们根据度量分析的结果,发现了我们前期没有做好的地方,对已有的管控规范进行修改和调整,对服务管控规则进行新增等。

  服务运行监控和整个治理框架中的其它核心模块之间的一些集成关系。通过集成关系的梳理,可以更方便理解服务运行监控分析在整个治理框架中的重要作用。

  无论是哪种你都可以看到。服务运行持续改进迭代(规则制定-》监控和独立分析-》规则执行),这个是一个不断优化,持续改进的过程。

  这个过程核心是规则驱动的,但是监控和度量分析又是关键手段,而最终的类似限流,服务降级仅仅是最终的执行措施或结果。

  因此一定不要简单地将微服务治理理解为设置了一个限流熔断策略就是微服务治理,或者上了一些限流熔断,服务链路监控工具就是微服务治理。

  就远行科技自己多年微服务治理方面的实践来说,其核心都是基于服务运行日志,服务链,性能,异常等监控不断的进行分析和梳理,不断的优化相应的管控治理规则,逐步落地实施的过程。

  在微服务架构实践过程中,由于很多接口是采用Http API接口方式进行调用,很多接口修改实际并不会引起编译构建期的错误。因此导致某个微服务接口修改后导致其它微服务模块功能出现异常的情况。当出现问题后,我们才在事后进行修复。

  通过上图的接互矩阵,可以很清楚的看到当某个接口出现变化的时候,究竟地对哪些微服务模块,哪些功能造成影响会那这些影响点就必须考虑配套的变更或者说在提交测试的时候,这些影响到的微服务模块或功能也需要进行测试。

  当前主流的微服务架构,本身就是一种去中心化的架构模式,因此微服务治理本身也是去中心化的。而对于服务注册发现中心,本身可以作为服务治理的一部分,但是无法完成所有的服务治理工作。也因此看到服务限流熔断,服务安全,负载均衡等往往还需要其它组件的配合,共同来完成微服务治理过程。

  能不能用一个框架来完成所有的服务治理工作,同时这个框架本身又是去中心化的架构。这个即前面谈到过的ServiceMesh服务网格,包括Istio开源实现。

  简单来说当前的ServiceMesh服务网格的思路就是通过下放Sidecar边车到各个微服务中的方式来实现管控流和数据流的分离,并彻底的去中心化。

  随着云原生,特别是容器云和DevOps的发展,这个问题得到了很好的解决,即我们可以在自动化的服务部署和交付过程中,自动的下放这个代理包,同时在边车模块有更新的时候我们也可以实现自动化的重新部署或灰度发布。

  也就是说通过ServiceMesh,可以很好地实现前面谈到的微服务开发框架和微服务治理框架的一个分离,通过由于有了DevOps和容器云的配合,又实现了整个过程完全对开发者透明,对已有的微服务无侵入。

  一开始的时候,直接google『服务治理』确实找不到相关定义,搜索『service governance』也没想要的结果,但是搜索『服务治理 英文』,搜到了一本书:

  由此得知,服务治理的英文其实就是『SOA Governance』,搜这个就能找到的页面了。是的,只有英文的。

  服务治理(SOA governance),按照Anne Thomas Manes的定义是:企业为了确保事情顺利完成而实施的过程,包括最佳实践、架构原则、治理规程、规律以及其他决定性的因素。服务治理指的是用来管理SOA的采用和实现的过程。

  我写过几个专栏文章,通过一些小故事说明白什么是微服务,什么是服务注册和服务发现。

  鹿老师的Java笔记:F版本SpringCloud1—大白话为啥要有微服务?啥是微服务?

  我们在分布式开发中经常听到的一个词就是“服务治理”。在理解“服务治理”的概念之前让我们先理解什么是分布式系统,分布式系统之间如何通过RPC(Remote Procedure Call,远程过程调用)方式通信,以及如何解决RPC框架存在的问题,这样才能真正地理解服务治理的核心思想。

  分布式系统指的是通过网络连接让多台计算机协同解决单台计算机所不能解决的计算、存储等问题,多台计算机之间通过 RPC 方式通信。在使用分布式系统前,首要解决的问题是如何拆解当前面临的问题。通过使用多台计算机分布式解决问题,让分布式系统中的每台机器都负责解决原问题的一个子集。一般来说,可以使用横向拆分法或者纵向拆分法对复杂的系统进行拆分。

  ◎横向拆分:在无状态系统中多部署几个实例,通过负载均衡方式协调每个实例所负载的计算量。

  ◎纵向拆分:将一个大应用拆分为多个小应用(例如,将系统拆分为用户、商品、订单服务),每个小应用都负责处理一部分业务。

  然而,虽然通过拆分法解决了计算或存储的问题,但是使用分布式技术进行开发会引发比单体应用更多的问题,比如网络异常、数据一致性及分布式系统性能等。因此,在使用分布式架构开发系统前,需要先深入理解分布式系统的概念和可能存在的异常。

  ◎服务器宕机:服务器宕机是分布式架构下最常见的异常之一。任何服务器都有可能发生故障,而且故障发生的类型、时间都不尽相同。所以,分布式系统一般允许部分服务器发生故障,但要求在部分服务器发生故障时不影响整个系统的正常使用。

  ◎网络异常:服务器与服务器之间通过网络通信,若在通信过程中出现消息丢失,则两个节点之间无法进行通信,会出现网络分化、消息乱序等网络问题。

  ◎分布式系统的三态:如果某个节点向另一个节点发起RPC请求,比如节点A向节点B发送一个消息,节点B根据收到的消息完成某些操作,并将操作的结果通过消息返回给节点A,那么这个RPC请求的执行结果可能有三种状态:成功、失败、超时(未知)。我们将这三种状态称为分布式系统的三态。在设计架构时需要考虑成功、失败、超时(未知)这三种状态的处理方式。

  ◎存储的数据丢失:对于有状态节点来说,数据丢失意味着状态丢失。通常只能从其他节点读取、恢复该存储数据的状态。

  分布式系统的副本指的是在分布式系统中为数据或服务提供的冗余。该副本可分为服务副本和数据副本两种类型。

  ◎服务副本:多个节点提供某种相同的服务,这种服务不依赖本地节点的存储状态,是一种无状态服务。

  ◎数据副本:在不同的节点上持久化同一份数据。当出现某一个节点存储的数据丢失时,可以从其他副本上读取该数据。数据多副本是分布式系统解决数据丢失异常的唯一方法,因为数据被分散或者复制到不同的机器上,所以如何保证各台主机之间数据的一致性,成为一个难点。

  对于分布式系统而言,服务副本非常容易控制,由于服务本身具备无状况特性,运维人员可以动态增加或者减少服务副本的数量,而不会影响服务接口返回数据的正确性。数据副本分布在不同的计算机上,从技术角度来看,数据的一致性面临着巨大的挑战。数据副本的一致性通常具有以下几种情况。

  ◎强一致性:任何时刻任何用户或节点都可以读到最近一次成功更新的副本数据。这是程度最高的一致性要求,也是实践中最难实现的一致性。

  ◎弱一致性:系统并不保证进程或者线程在任何时刻访问数据都会返回最新的更新过的值。系统在数据成功写入之后,不承诺立即读到最新写入的值,也不承诺最终多久之后可以读到最新值。

  ◎最终一致性:数据一旦更新成功,各个副本上的数据最终将达到完全一致的状态,但需要一定的时间。

  然而,分布式系统也存在一些复杂特性,比如分布式系统的三态性、异构性、透明性、并发性、可扩展性等。我们在应用分布式系统的过程中要仔细斟酌这些特性的优势和副作用。

  ◎异构性:由于分布式系统基于不同的网络、操作系统、计算机硬件和编程语言,因此必须考虑采用一种通用的网络通信协议来屏蔽异构系统之间的差异。开发人员一般选择中间件来屏蔽这些差异。

  ◎透明性:分布式系统中任意组件的故障及主机的升级或迁移,对用户来说都是透明的。

  ◎并发性:应用分布式系统的目的是更好地共享资源,所以系统中的每个资源在并发环境下都必须是安全的。

  ◎可扩展性:随着业务量的增加,系统必须具备可扩展性,以应对因业务量增长而增加的外部流量。

  ◎故障独立性:任何计算机都有可能发生故障,而且各计算机发生的故障类型不尽相同,发生故障的时间也各不相同。所以,分布式系统一般允许发生部分故障,而不影响整个系统的正常使用。

  ◎数据一致性:因为数据被分散或者复制到不同的机器上,所以需要保证各台服务器之间数据的一致性。

  ◎负载均衡:由于分布式系统是多机协同工作的系统,因此为了提高系统的整体效率和吞吐量,必须考虑最大化地发挥每个节点的作用,以最大化地利用资源,避免某个节点过载或者浪费资源。

  ◎系统的性能:系统每秒的事务处理能力,通常用TPS(Transactions Per Second)来衡量。

  ◎系统的可用性:系统在面对各种异常时可以正确提供服务的能力。该指标可以用系统停服的时间与正常服务时间的比例来衡量,也可以用某功能的失败次数与成功次数的比例来衡量。系统的可用性是分布式系统的重要指标,是系统容错能力的体现。

  ◎系统的可扩展性:分布式系统通过扩展集群的机器规模来提高系统性能(增大接口吞吐量、降低接口延时、增大接口并发量)、存储容量、计算能力的特性。

  RPC(Remote Procedure Call,远程过程调用)是一种进程间通信方式,也是一种技术思想。使用 RPC 技术时,允许本地程序通过网络调用另一台服务器上的函数或者方法,具体调用过程一般由 RPC 框架实现,不用编码实现。即无论是调用本地函数还是调用远程函数,我们编写的调用代码在本质上基本相同。

  RPC框架要向服务调用方和服务提供方屏蔽各类复杂性操作,比如负载均衡、序列化和反序列化、网络重试、超时等,主要由客户端、服务器端和注册中心3种角色构成,整体架构如图3-1所示。

  ◎客户端(Client):调用远程服务的服务消费方。客户端调用远程服务就像调用本地函数一样,客户端负责序列化、反序列化、连接池管理、负载均衡、故障转移、超时管理、异步管理等。

  ◎服务器端(Server):暴露服务的服务提供方。服务器端如同实现一个本地函数一样来实现远程服务提供,服务器端需要做收发包队列、I/O线程、工作线程、序列化及反序列化等工作。

  一次RPC调用流程主要由5部分组成,分别是客户端、客户端存根、服务器端存根、服务提供端和网络传输,其调用流程如图3-2所示。

  ◎客户端存根:用于存放服务器端的地址信息,将客户端的请求参数等信息打包成网络消息,再通过网络传输发送给服务器端。

  ◎服务器端存根:接收客户端发送过来的请求消息并解包,然后调用本地服务处理。

  业务在刚开始时都是单体应用,随着用户量和访问量的增加,在架构层面会发生变化,逐步由单体应用开发转为分布式应用开发,比如把单体应用中的每个模块都按照特定的方法拆分成一组独立的服务,服务与服务之间通过HTTP或者RPC方式调用。随着业务量的逐步增加,服务的数量也逐步增加。这时维护服务的URL地址就变得非常麻烦,所以需要设计一套系统来统一管理每个服务所对应的URL地址。这套系统就叫作注册中心。当有多个服务时,消费者需要根据规则来调用相关服务,实现软负载均衡,以达到资源利用率最大化的目的。因此,服务注册、服务发现、负载均衡、流量削峰、版本兼容、服务熔断、服务降级、服务限流等方面的问题,都是因服务拆分所引发的一系列问题。如何解决这些问题,让服务更稳定地运行,就叫作服务治理。

  总体来说,服务治理指的是企业为了确保事情顺利完成而实施的内容,包括最佳实践、架构原则、治理规程、规律及其他决定性的因素。下面针对服务治理过程中的各个环节做相关说明。

  (1)服务:它是分布式架构下的基础单元,包括一个或一组软件功能,其目的是不同的客户端通过网络获取相应的数据,而不用关注底层实现的具体细节。以用户服务为例,当客户端调用用户服务的注册功能时,注册信息会被写入数据库、缓存并发送消息来通知其他关注注册事件的系统,但是调用方并不清楚服务的具体处理逻辑。

  (2)注册中心:它是微服务架构中的“通讯录”,记录了服务和服务地址的映射关系,主要涉及服务的提供者、服务注册中心和服务的消费者。在数据流程中,服务提供者在启动服务之后将服务注册到注册中心;服务消费者(或称为服务消费方)在启动时,会从注册中心拉取相关配置,并将其放到缓存中。注册中心的优势在于解耦了服务提供者和服务消费者之间的关系,并且支持弹性扩容和缩容。当服务需要扩容时,只需要再部署一个该服务。当服务成功启动后,会自动被注册到注册中心,并推送给消费者。

  (3)服务注册与发布:服务实例在启动时被加载到容器中,并将服务自身的相关信息,比如接口名称、接口版本、IP地址、端口等注册到注册中心,并使用心跳机制定期刷新当前服务在注册中心的状态,以确认服务状态正常,在服务终止时将其从注册表中删除。服务注册包括自注册模式和第三方注册模式这两种模式。

  ◎自注册模式:服务实例负责在服务注册表中注册和注销服务实例,同时服务实例要发送心跳来保证注册信息不过期。其优点是,相对简单,无须其他系统功能的支持;缺点是,需要把服务实例和服务注册表联系起来,必须在每种编程语言和框架内部实现注册代码。

  ◎第三方注册模式:服务实例由另一个类似的服务管理器负责注册,服务管理器通过查询部署环境或订阅事件来跟踪运行服务的改变。当管理器发现一个新的可用服务时,会向注册表注册此服务,同时服务管理器负责注销终止的服务实例。第三方注册模式的主要优势是服务与服务注册表是分离的,无须为每种编程语言和架构都完成服务注册逻辑。相应地,服务实例是通过一个集中化管理的服务进行管理的;缺点是,需要一个高可用系统来支撑。

  (4)服务发现:使用一个注册中心来记录分布式系统中全部服务的信息,以便其他服务快速找到这些已注册的服务。其目前有客户端发现模式和服务器端发现模式这两种模式。

  ◎客户端发现模式:客户端从服务注册服务中查询所有可用服务实例的地址,使用负载均衡算法从多个服务实例中选择一个,然后发出请求。其优势在于客户端知道可用服务注册表的信息,因此可以定义多种负载均衡算法,而且负载均衡的压力都集中在客户端。

  ◎服务器端发现模式:客户端通过负载均衡器向某个服务提出请求,负载均衡器从服务注册服务中查询所有可用服务实例的地址,将每个请求都转发到可用的服务实例中。与客户端发现一样,服务实例在服务注册表中注册或者注销。我们可以将HTTP服务、Nginx的负载均衡器都理解为服务器端发现模式。其优点是,客户端无须关注发现的细节,可以减少客户端框架需要完成的服务发现逻辑;客户端只需简单地向负载均衡器发送请求。其缺点是,在服务器端需要配置一个高可用的负载均衡器。

  (5)流量削峰:使用一些技术手段来削弱瞬时的请求高峰,让系统吞吐量在高峰请求下可控,也可用于消除毛刺,使服务器资源的利用更加均衡、充分。常见的削峰策略有队列、限频、分层过滤、多级缓存等。

  (6)版本兼容:在升级版本的过程中,需要考虑升级版本后新的数据结构能否理解和解析旧的数据,新协议能否理解旧的协议并做出预期内合适的处理。这就需要在服务设计过程中做好版本兼容工作。

  (7)服务熔断:其作用类似于家用的保险丝。当某服务出现不可用或响应超时的情况时,已经达到系统设定的阈值,为了防止整个系统出现雪崩,会暂时停止对该服务的调用。

  (8)服务降级:在服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略性地降级,以此释放服务器资源,保证核心任务的正常运行。降级时往往会指定不同的级别,面对不同的异常等级执行不同的处理。

  (9)服务限流:服务限流可以被认为是服务降级的一种。它通过限制系统的输入和输出流量来达到保护系统的目的。一般来说,系统的吞吐量是可以被测算的。为了保证系统的稳定运行,一旦达到阈值,就需要限制流量。限制措施有延迟处理、拒绝处理或者部分拒绝处理等。

  (10)负载均衡策略:它是用于解决一台机器无法处理所有请求而产生的一种算法。当集群里的1台或者多台服务器不能响应请求时,负载均衡策略会通过合理分摊流量,让更多的服务器均衡处理流量请求,不会因某一高峰时刻流量大而导致单个服务器的 CPU或内存急剧上升。

  本文节选自《架构演变实战:从单体到微服务再到中台》这本2022年刚出版的新书

  书里通过真实案例实战的方式完整地讲述了如何从一个单体架构逐步转型到中台的历程!