作者介绍张震,宜信技术研发中心高级架构师,负责基础系统架构、服务治理、监控平台、微服务构建、DevOps平台、自动化测试框架和电子签名的演进和优化、短信、电子邮件等应用系统。早年在IBM中国研发中心工作,负责IBMWebSphere应用服务器的设计和开发。目前主要从事微服务架构的实现、微智能设计思想的应用、虚拟化技术的应用、共识计算的研究。本文将包括以下内容:1.经典微服务架构的特点和问题2.微服务计算平台的设计思想和抽象模型3.搭建微服务计算基础的三件事服务注册与发现服务上下文感知4.总结1.经典微服务架构的特点和问题一个经典的微服务架构一般包括两部分:API网关和一组微服务。API网关是唯一的请求入口,同时负责负载均衡、路由安排、故障转移等工作。经典微服务架构图(来源网络):关于经典微服务架构的文章很多。这里分享一下我们在实践经典微服务架构中遇到的一些问题:“笨重”的API网关,因为负责各种核心功能,不能灵活扩展,比如负载均衡策略,可能是每个微服务类型的要求不同,难以灵活变化;随着越来越多的微服务接入,每个API网关也集成了大量的功能。API网关本身需要一个高可用的保证,这是经典架构所不具备的。随着越来越多的微服务接入后端,也会带来很多稳定性问题。它和微服务同样需要两套运维方式。产生额外费用。服务注册和发现还是传统模式,级联agent不能级联,长连接也有限制,无法解决跨大网段、跨机房、跨IDC中心的问题。心跳机制比较简单,只是从连接层面考虑。服务本身没有上下文和监控,需要依赖第三方实现。故障转移机制单一,只能检查连通性。对业务异常没有感知,也就是不能根据业务异常进行切换。没有自动高效的重试机制,需要考虑API网关的改造。几乎没有隔离机制,需要借助第三方技术来解决。微服务实现目前还没有统一的技术栈支持,目前还处于原理规范阶段。服务编排依赖人工,没有动态编排能力。整体来看,经典的微服务架构还不够“智能化”,所以我们设计并着手研发新一代的微服务计算平台,希望让它能够充分发挥微服务架构的优势和特点。二、微服务计算平台的设计思路和抽象模型1、“微智能”的设计思路“微智能”的概念起源于智能家居,是智能硬件领域的创新思想。当提到“聪明”这个词时,它通常是相对于人而言的。智能家居通过“智”的体现,可以更好地服务于人们的生活。因此,我们思考系统或服务是否也能体现“智能”。如果与微服务相结合,将使其工作得更“聪明”。反映真实世界,用“自动化”手段捕捉真实情况,尽可能提取有效“信息”。微服务实际上是将原来单一的系统或“重”服务拆分开来,这意味着服务的种类和服务实例的数量会成倍增加,人工编排或编排的手段会变得繁琐和滞后。自动发现使微服务生命周期管理的初始阶段自动化。2)自我维护:即形成一个“闭环”反馈回路,然后将“输入”或“中间”或“结果”信息反馈到系统中,合并成新的“输入”或“中间”或“结果”信息。现实世界中的信息瞬息万变,为了尽可能接近现实,需要不断迭代。除了更多的服务实例(规模增长),微服务架构还意味着更多“多变复杂”的服务变更(变更频率增长),自维护实现微服务生命周期管理变更的自动化。3)自动适配(adaptation):自动适配扩展了自动发现+自我维护的思想外延,是“智慧”的体现。根据自动发现的信息进行相应的处理(初始适配);根据自我维护的反馈,不断调整(迭代适应)。比如服务降级的阈值,其实这个阈值是在不同时间不同的资源使用情况下动态变化的。在数百个服务实例的级别上,已经不能再依赖手动调整了。相反,每个服务实例都需要基于上下文和环境。历史状态的分析自主调节。因此,微智能设计思维的三大核心原则是构建“智能”微服务计算平台的基本指导思想。2、“伪社交”分布式设计有了微智能的思想,我们需要重新认识“服务”。什么是微服务,社区里有很多文章分享相关的内容。我们理解服务的“微”体现在:细粒度的服务能力:一个服务实例只完成一种或几种业务,或者只有一种或几种能力。完全独立的部署结构:每个服务实例可以独立部署服务能力可以编排:不同的服务实例需要协同完成“更大”的业务更多同类型实例:业务类型决定服务类型,业务负载大小决定了某种服务类型的实例数量,当然这也可能意味着更稳定的服务输出。这里有一个有趣的想法:社会是一群相互合作的人(个人)。每个人都可能拥有几种技能,并利用这些技能参与社会分工与合作。具有相同技能的人可以协同工作,提高生产效率,提供高可靠的生产输出;拥有不同技能的人可以一起完成某项任务,形成一条生产线。其实可以发现,微服务的特性和人类社会的运行方式非常相似。服务实例是个体,服务能力是技能。允许服务实例具有多种服务能力。具有相同服务能力的实例可以视为同一类型的实例。由多个同类型实例组成的集群可以实现负载均衡和高可用。可以将类型实例编排在一起以完成业务流程。我们称这种分布式设计为“伪社会化”。“伪社交”分布式设计抽象图:“伪社交”分布式设计的特点:服务计算节点与服务能力之间没有必然联系,这是与传统分布式设计的重要区别。服务计算节点是运行资源的载体,服务能力是业务逻辑的载体。服务计算节点允许多种服务能力。服务能力有两种状态:active(可以使用),inactive(存在但不可用)。服务能力是独立的和可组装的。服务集群其实就是服务能力的集群,这也是区分传统单体架构集群还是SOA服务集群的关键。业务协同过程实际上是业务能力协同过程,而不是业务计算节点协同过程。由于协作过程中服务能力的可变性,可以动态定义服务能力集群,即软件定义服务集群(SDSC)。这里可能会有一个疑问:为什么允许某个服务计算节点拥有多种服务能力?这是不是一种“倒退”,不符合微服务的原则?其实主要有两个原因:资源占用:在实际实现过程中,很难保证每个服务能力都可以独占计算节点,这样的实现实际上过于极端。与传统架构相比,微服务的服务实例数将增加数倍甚至数十倍,单纯通过增加资源投入难以满足部署需求。服务编排的需求:这是比较重要的一点。服务输出体现在服务能力上(再次强调,不是服务计算节点),也是“微”的体现。由于业务能力可以被激活,也可以“休眠”,因此复合能力节点具有多种业务能力输出的可能性。例如,一个业务计算节点可以在一段时间内属于某个业务能力集群,在另一段时间属于另一个业务能力集群,这样可以最大限度地利用计算资源。下面通过两个例子来说明“准社会化”分布式设计的应用。实例一:短信系统是一个常见的高并发系统。在互联网环境中,Peaktime可能是由各种营销活动引起的。常规的方法是增加资源,但现实是资源池是有限的,大部分时间Peaktime会影响到整个营销活动链的系统,这些系统需要增加资源,资源池很快就会被分割。在“准社会化”的分布式设计下,通过服务能力的快速切换,可以将当前时间段处于休眠状态或服务能力较小的部分计算资源集中到Peaktime的服务能力上。Peaktime过去后,可以快速恢复原来的集群。同时,可以发现另一个特点:软件定义的集群。该功能将在以后的分享专题中具体说明。实例2:在P2P业务中,线下签单通常在白天进行,晚上没有业务,签单数据的统计工作是T+1模式,在晚上进行。传统方式是部署两个完全独立的系统,而“准社会化”的分布式系统通过复合能力节点通过服务能力切换的方式实现同??一套计算资源的复用。计算节点抽象模型下一步是将微智能和类社会分布式设计思想统一起来,为微服务计算平台构建计算节点抽象模型。它遵循以下原则:服务能力是实现业务逻辑的唯一途径,每个能力只包含一个业务逻辑。服务能力的实现遵循同一套技术实现框架,只是业务逻辑不同,运行机制和运维机制完全相同,每个计算节点都是平等的,只是计算资源占用不同,运行机制、运维机制等完全相同。计算节点的分工由服务能力决定。部署的计算节点包括至少一个服务能力计算节点实现,遵循同一套技术实现框架,该实现框架提供运行服务能力的能力。容器计算节点集群的构建方式自动发现,集群元数据的维护由计算节点集群自行维护。服务能力的发现方式是自动发现,服务调用元数据的维护由计算节点集群自行维护。服务调用过程应具有自适应能力,尽量保证服务调用的顺畅,并能够具有一定的独立处理能力,让服务能力在面临风险时。集成编排,服务编排后的运行流程自适应处理异常或风险。计算节点抽象模型:服务能力是一种计算能力,分为基础服务能力和业务服务能力。基础服务能力是构建计算平台的前提,也为计算平台服务的调用、监控、运维提供支撑。基础服务能力其实是整个计算平台的基石,在以后的分享专题中会一一讲解。业务服务能力是基于实际业务需求实现的服务能力。根据以上原则,服务计算节点还提供三种基础支持:服务能力的生命周期管理:值得注意的是,服务能力可以组装也可以卸载。这个过程分为Soft模式和Hard模式。Soft模式下,服务能力(如jar包)的实现仍然通过配置存在;在困难模式下,配置和实现是一起组装或卸载的。在实际应用中,Soft模式更加灵活,可以通过节点升级来改变服务能力。服务能力实现框架:为实现业务逻辑提供统一的编程和运行框架。组件管理支持:服务能力在业务层面是原子,但在实现层面可以分解成组件。组件是具有特定逻辑和通用逻辑的代码。支持常用的编程组件:维护统一标准的技术栈,也加速服务能力的发展。一般包括:定时任务、HTTP服务器、HTTP客户端、内存队列异步处理、多线程或并行编程支持。当然通信级别根据实际选择而定,我们使用HTTP作为标准通信。计算节点自主管理:支持实际运行和运维需求。元数据管理:例如,每个计算节点需要一个唯一的ID来标识自己(就像一个人的身份证),该ID在第一次运行时创建并持久化,以便再次运行时ID保持不变;一些服务能力的运行会产生临时文件,这就需要计算节点提供一个“地方”(临时目录)供其使用。节点自动升级/回滚:这是所有分布式系统中最重要的特性之一。可以大大提高大规模节点的变更效率,特别适合微服务架构下。这个变更过程包括两个方面:计算节点配置和实现变更,服务能力配置和实现变更。节点配置管理:负责提供实际的配置读写接口,持久化自身的运行时配置和服务能力。当然,计算节点本身的管理还有很多扩展,需要根据实际需要来定义。3.构建微服务计算的基础三件事要在微服务计算平台上实现服务治理,首先要解决三个基础:服务注册与发现、服务监控、服务调用控制。一、服务注册与发现1)服务注册服务注册有两种经典方式:显式配置:手动配置服务接口信息(服务名称、服务URI等)到服务注册中心。WebServiceUDDI就是这种模式。它的问题是需要手动收集服务接口信息。这个过程可能会造成信息滞后或错误,运维成本高。代码实现:调用服务注册中心客户端向服务注册中心发送服务接口信息。典型用例基于Zookeeper服务注册表。其优点是可以通过代码采集服务接口的URI,比人工采集更加自动化。但它也存在以下问题:需要编写专门的代码埋点,与服务注册客户端紧耦合:如果使用Zookeeper,需要依赖其jar包。服务注册码与服务接口代码的上下文紧密耦合:服务注册码必须在特定的位置使用,也可能包含特定的服务信息,可以通过人工编程实现。由于不同的系统由不同的团队开发,因此需要管理系统。“TopDown”规定了服务注册的编程。一旦出现“不按套路”的情况,就会出现各种运维问题。基于上述计算节点模型,我们的微服务注册流程如下:基于计算节点提供的Http服务框架实现通过HTTP暴露功能的服务能力(如Http服务能力A)。统一技术栈的目的之一也是为服务注册做准备。Http服务能力A组装完成后,基础服务能力“ServiceCapabilityProfile”对其进行剖析。profiling的过程其实就是解析编程模型的过程。提取的信息包括IP、上下文路径、服务接口的URL、服务接口对应的实现方法、方法入参的模式等。这个过程实现了服务的自动发现。服务能力画像完成后,会将画像数据传递给基础服务能力“心跳客户端”。心跳客户端通过心跳上行链路将服务接口数据发送给服务注册中心。我们的服务注册流程是基于心跳系统的,服务注册是心跳交易之一。服务注册中心其实就是基础服务能力“心跳服务器”的功能,它的载体是另一个计算节点(如图服务计算节点B),这也是计算节点等价性的体现,因为任何一个具有服务端能力的心跳计算节点都可以作为服务注册中心。服务注册:常规模式服务注册:“心跳级联代理??”模式在大规模部署服务计算节点时,经常会遇到跨大网段、跨机房、跨IDC中心、白名单IP策略等问题。因此,心跳系统也支持“心跳级联代理??”模式,允许建立多级心跳组。每个组由若干个“代理”心跳服务器组成。它们只负责转发心跳信息,所以服务注册信息也依赖于这个过程转发到服务注册中心。服务注册:在一些特殊的业务场景下,多级服务注册中心模型对服务注册信息更新延迟的容忍度较低。此时级联心跳的计算节点也作为服务注册中心。如下图所示,节点B是一级服务注册中心(以下简称一级中心),节点C是二级服务注册中心(以下简称二级中心)。一级中心会存储提交给自己的服务注册信息,同时也会将这些信息转发给上一级服务注册中心。在二级中心可以看到所有下级中心的服务注册信息。这种模式可以实现更快的服务发现,因为同级节点只需要经过同级服务注册中心就可以发现其他节点的服务能力。下面结合服务发现进行详细说明。服务注册中心依赖TTL来管理服务接口注册信息的生命周期。我们定义生命状态如下:Alive:服务接口是健康的,可以查询。可疑死亡(Dying):由于网络延迟等原因导致的假死状态。服务接口健康状态存疑,可查询。有可能在1~2个生命周期后收到上行心跳,就可以回到Alive状态。死(Dead):超过较大的TTL,基本认为服务接口死了,其接口信息被隔离,无法查询。消失(Disappear):超过了肯定死掉的TTL,我觉得服务接口是可以抹掉的,最终会从服务中心掉线。其接口信息是隔离的,不可查询。另一个关键点是服务接口名称的定义。它应该是一个全局唯一的名称,因为在多个服务能力相互调用时,服务接口就是目标。服务画像时,自动生成服务接口名称,提取如下三类信息:计算节点类型名称(与业务计算节点相关):计算节点类型由业务语义决定,如MonitoAgent,SMSGateway、HealthManager等Http服务组件类型名(与服务能力相关):对外提供的Http服务组件的类名缩写,如MDFListenServer、NodeOperHandleServer、DigitSignServer等Context路径(与服务接口相关):相对到Http服务根目录的路径,比如/ma/put/mdf、/hm/cache/q、/rtntf/oper等。它们共同构成了服务接口名称,例如:healthmanager-HealthMangerServerWorker-/hm/cache/qruntimenotify-RuntimeNotifyServerWorker-/rtntf/operhbserveragent-HeartBeatServerListenWorker-/heartbeat2)服务发现服务发现的本质是通过服务查询服务注册中心接口名称,服务注册中心根据一定的策略返回服务接口的可用地址列表,服务调用者也可以根据一定的策略使用地址列表。微服务计算平台的服务发现流程如下:业务服务能力X以服务接口为参数,调用组件API(每个服务能力组件都有)。组件API内部是调用heartbeatclient向服务注册中心查询服务接口。值得注意的是,除了第一次获取服务接口的信息外,这个过程出于性能的考虑是独立的。心跳客户端可以通过下行心跳不断更新已经使用过的服务接口信息,并通过TTL机制自动过期。哪些服务接口信息已经很久没有使用了。服务注册中心按照一定的策略(授权访问策略、隔离策略等)返回地址列表。业务服务能力X获取到服务接口地址列表后,可以按照一定的轮询策略(RoundRobin、weight等)进行使用。心跳级联代理??模式下的服务发现与常规模式类似,这里不再赘述。多级服务中心模式下的服务发现:如上所述,在多级服务注册中心模式下,可以获得更快的服务发现。从heartbeatclient的角度来看,其实没有什么区别,但是如果是查询同级的服务接口,不用去二级中心,直接在一级中心就可以找到;对于跨层级查询服务接口,需要从二级中心获取,并缓存在一级中心,从而加速跨层查询。需要注意的一点是,一级中心的缓存也是TTL,生命周期比二级中心短,这是性能和时效相互适应的结果。虽然从level1查cache很快,但是level1center无法判断跨层服务是否存活,所以long-termcache可能是错误的信息。缩短TTL时间的目的是为了更快地更新跨级服务的地址信息。服务接口故障快速反馈:当业务服务能力X调用Http服务能力A遇到异常时,服务能力实现框架会自动捕获异常信息并发送系统异常(Timeout、SocketException等)和部分业务异常(基于策略)到服务注册中心,这个过程不必等到心跳周期到来,而是立即触发,这样服务注册中心就可以快速隔离这些服务接口。其他有意调用该服务接口的服务能力通过心跳下游获取地址列表更新。这种方式可以弥补TTL机制可能带来的延迟。另外解释一下为什么不用类似Zookeeper的长连接(虽然时效性更好),主要有以下几个原因:长连接给服务注册中心带来很大的压力,而长连接连接数意味着必须支持大量的连接数,而传统的PC服务器可以支持数千个长期连接数已经是极限了。在微服务架构下,如果实例数量在这个数量级,还可以接受,但如果是万级实例,对硬件配置的要求就太高了,大量的长连接在系统层面也是一个问题。存在管理问题。跨大网段、跨机房、甚至跨IDC中心都很难实现长连接,甚至可能因为某些IP安全策略(隔离)而变得不可用。长连接的超时机制很难控制,太短会造成“中断”的错觉,太长会造成“假生存”,受网络层影响很大。长连接也不能支持级联来实现服务规模的扩展能力。
