在微服务架构中,我们还需要ESB吗?
从集中式ESB 到 分布式ESB Service Mesh
问题提出:
很多人理解ESB企业服务总线是一种集中式服务治理的架构,服务总线实际上是一种服务治理的架构,并不是只有集中式ESB,还有分布式ESB。分布式的服务总线已经出来,Service Mesh未来会成为一种新的标准。
微服务是近几年.术社群讨论很多的一种软件架构方式,可以说是SOA的现代版本、时尚版本。不过这次浪潮不是由大公司倡导的,而是由工程师们引领的。比如,它采用工程师们熟悉的RESTful接口,而不是笨重的WebService,也不需要一大堆昂贵的中间件。
第一,目前移动APP开发越来越重要。就算是html的客户端,也大量采用了html5技术。在这种情况下,工程师们都习惯通过RESTful接口与后端通讯,甚至他们把职位也简单的划分为前端工程师和后端工程师。这导致REST服务成了刚需。原来的软件可以拒绝提供Web Service接口,但现在的则不能不提供RESTful接口。人人都用,用量很大。这为微服务化提供了天然的契机。
第二,性能也越来越重要。为什么?只要服务一慢,APP的用户体验就差呀。原来的SOA体系不怎么提性能。一方面是故意不说,你想WebService各种打包解包就要消耗多少CPU周期和网络带宽,性能肯定不是优势。二是如果性能不好,正好买大厂商的昂贵的服务器和lincense呀。但工程师们不吃这一套。明明很简单就可以实现高性能,为什么要搞那么复杂?把微服务集群化、搞搞读写分离不就好了吗?
第三,替换比利旧重要。SOA很多的应用场景都是在对已有应用的打通,比如你买了ERP 的软件,又买了另一家的软件,还有以前投资定制开发的软件。这些软件都很贵,要像祖宗一样供起来的,轻易不敢改动,改动成本很高。所以要尽量保留,要通过SOA的方式对接在一起。而搞微服务的那些人呢?他们的理念是“Design for replacement”,设计的每个微服务都要非常容易被抛弃、被替换。拥抱不断变化的业务,快读迭代开发。那些旧的包袱他们压根不想搭理,天天想的是怎么替掉它们算了。
所以,看上去我们不需要ESB了。ThoughtWorks的首席科学家Matin Fowler也不赞同在微服务架构中继续用ESB。他的考虑是说没有必要把一些逻辑集中在像ESB这样的中介结构中,这样与系统尽量解耦的初衷是背离的。
然而,事情似乎没有那么简单。我们在实践中发现,还是有一些需求,如果用类似ESB的机制,可能更容易满足。
没错,但是一个问题来了,原来SOA架构中推行的那些东西:ESB、BPEL、CEP,Composite service 这些都没有用?或者是不是有替代者?
比如,ESB是解决服务消费者和服务提供者之间的点对点连接关系的。点对点连接当然不如大家都连到一个“总线”上,这样就会实现物理位置、传输协议等多个方面对透明。这在微服务架构中有用吗?
Service Mesh (分布式ESB)是下一代微服务架构核心
Service Mesh又译作“服务网格”, 也有人翻译为”服务啮合层”.
Service Mesh 是一个基础设施层,用于处理服务间通信。云原生应用有着复杂的服务拓扑,Service Mesh 保证请求可以在这些拓扑中可靠地穿梭。在实际应用当中,Service
Mesh 通常是由一系列轻量级的网络代理组成的,它们与应用程序部署在一起,但应用程序不需要知道它们的存在。
下图展示了服务网格的典型边车部署方式:
图中应用作为服务的发起方,只需要用最简单的方式将请求发送给本地的服务网格代理,然后网格代理会进行后续的操作,如服务发现,负载均衡,最后将请求转发给目标服务。
In a nutshell, a Service Mesh is an inter-service
communication infrastructure. With a service mesh, A given Microservice
won't directly communicate with the other microservices. Rather
all service-to-service communications will take places on-top of a
software component called service mesh (or side-car proxy).
当有大量服务相互调用时,它们之间的服务调用关系就会形成网格,如下图所示
在上图中绿色方块为服务,蓝色方块为边车部署的服务网格,蓝色线条为服务间通讯。可以看到蓝色的方块和线条组成了整个网格,我们将这个图片旋转90°,就更加明显了:服务网格呈现出一个完整的支撑态势,将所有的服务”架”在网格之上
原理
Service
Mesh 基本原理
如果用一句话来解释什么是 Service Mesh,可以将它比作是应用程序或者说微服务间的 TCP/IP,负责服务之间的网络调用、限流、熔断和监控。对于编写应用程序来说一般无须关心 TCP/IP 这一层(比如通过 HTTP 协议的 RESTful 应用),同样使用 Service Mesh 也就无须关系服务之间的那些原来是通过应用程序或者其他框架实现的事情,比如 Spring Cloud、OSS,现在只要交给 Service Mesh 就可以了。
从最原始的主机之间直接使用网线相连
网络层的出现
集成到应用程序内部的控制流
分解到应用程序外部的控制流
应用程序的中集成服务发现和断路器
出现了专门用于服务发现和断路器的软件包/库,Twitter’s Finagle和 Facebook’s
Proxygen。这时候还是集成在应用程序内部
出现了专门用于服务发现和断路器的开源软件,如:NetflixOSS ecosystem
最后作为微服务的中间层Service
Mesh出现
Service Mesh的优点
[if !supportLists]1. [endif]应用程序间通讯的中间层;
[if !supportLists]2. [endif]轻量级网络代理;
[if !supportLists]3. [endif]应用程序无感知;
[if !supportLists]4. [endif]解耦应用程序的重试、超时、监控、追踪和服务发现;
不妨考虑一下贵企业在微服务方面的计划。也许贵企业打算在Kubernetes集群中运行10个服务、50个服务、100个服务或1000个服务。那么如何以一种高效而统一的方式在新的微服务和容器环境中管理所有那些服务?
你知道哪个服务在跟哪个服务联系、是否允许它们这样?这种通信是否安全?出现故障时,你如何来调试某个服务?如何在不影响所有应用程序的情况下添加跟踪或日志功能?你知道发布其中一个服务的新版本对上下游服务的性能或质量有何影响吗?
Service Mesh有助于回答那些问题。作为插入在微服务和网络之间的一个透明的基础设施层,它为你在应用程序的通信路径中提供了单一点,以便插入服务、收集遥测数据。你无需更改应用程序就可以做到这一点。
3. 方案
目前社区Service Mesh的开源解决方案有:Buoyant 公司推出的 Linkerd 和 Google、IBM等厂商牵头的 Istio。Linkerd 更加成熟稳定些,Istio 功能更加丰富、设计上更为强大,社区相对也更加强大一些。所以普遍认为Istio 的前景会更好,但是毕竟还处于项目的早期,问题还很多。
3.1 Istio 介绍
Istio是由Google、IBM和Lyft开源的微服务管理、保护和监控框架。Istio为希腊语,意思是”起航“。官方中文文档地址:https://istio.doczh.cn
Google Cloud首席技术官UrsHölzle表示:“我的期望是,90%的Kubernetes用户在两年后使用Istio。它与Kubernetes所提供的非常吻合,几乎感觉就像Kubernetes的下一次迭代。这是由同一个团队完成的,两者合作得很好。Istio刚刚1.0。到目前为止,大家对它还比较陌生。今天它的用量非常少,因为直到本周它才生产就绪。”Hölzle还说了这么一句话:“可以说你从Istio获得的价值会大于Kubernetes。
Hölzle认为,Istio将加速企业对公有云的采用,因为它可以在内部部署和云之间实现更高的同质性:“公司可以决定将所有内容都移到Istio,包括他们不想重写的旧代码,这是非常合理的——更像是包装而不是重写。我们相信GKE
on-prem是许多用户深入云计算的方式。它与现代云思维非常融合,但它让用户可以选择何时何地迁移。”“你想什么时候迁移,选择哪个供应商,都可以。我们希望许多公司能够将其作为云计算之旅的核心,使云计算之路更加顺畅。”“一旦人们熟悉了Kubernetes和Istio的管理和编排方式,云就不会太可怕了。
不妨设想一下,在平时理解的微服务开发过程中,在没有Istio这样的服务网格的情况下,要如何开发我们的应用程序,才可以做到前面列出的这些丰富多彩的功能? 这数以几十记的各种特性,如何才可以加入到应用程序?
无外乎,找个Spring Cloud或者Dubbo的成熟框架,直接搞定服务注册,服务发现,负载均衡,熔断等基础功能。然后自己开发服务路由等高级功能,接入Zipkin等Apm做全链路监控,自己做加密、认证、授权。想办法搞定灰度方案,用Redis等实现限速、配额。 诸如此类,一大堆的事情, 都需要自己做,无论是找开源项目还是自己操刀,最后整出一个带有一大堆功能的应用程序,上线部署。然后给个配置说明到运维,告诉他说如何需要灰度,要如何如何,如果要限速,配置哪里哪里。
就是transformation,routing这些和business logic相关的orchastration,放到服务自身去做。这只是去掉了ESB的业务层的转换和路由,而而网络协议的转换调用适配,是去不掉的,而网络协议的转换调用适配,是去不掉的。而业务层无论是放在esb还是放在服务本身其实是无关紧要的,并不是说放在esb就工作量大,也并不是说放在服务本身就工作量小,所以,无论怎么样,核心的东西是去不掉的服务发现,服务注册,服务安全,熔断,监控,AB测试,负载均衡。。
这些工作,相信做微服务落地的公司,基本都跑不掉,需求是现实存在的,无非能否实现,以及实现多少的问题,但是毫无疑问的是,要做到这些,绝对不是一件容易的事情。
这里就有一个很严肃的问题, 给每个业务程序的开发人员: 你到底想往你的业务程序里面塞多少管理和运维的功能? 就算你hold的住技术和时间,你有能力一个一个的满足各种运维和管理的需求吗?当你发现你开始疲于响应各种非功能性的需求时,就该开始反省了: 我们开发的是业务程序,它的核心价值在业务逻辑的处理和实现,将如此之多的时间精力花费在这些非业务功能上,这真的合理吗? 而且即使是在实现层面,微服务实施时,最重要的是如何划分微服务,如何制定接口协议,你该如何分配你有限的时间和资源?
Istio 超越 spring cloud和dubbo 等传统开发框架之处, 就在于不仅仅带来了远超这些框架所能提供的功能, 而且也不需要应用程序为此做大量的改动, 开发人员也不必为上面的功能实现进行大量的知识储备。
Istio架构图:
Istio架构分为控制层和数据层。
Envoy,在Istio中扮演的就是数据面板,而其他我们下面将要陆续介绍的Mixer、Pilot和Auth属于控制面板。上面我给出了一个类比:Istio中Envoy (或者说数据面板)扮演的角色是底层干活的民工,而该让这些民工如何工作,由包工头控制面板来负责完成。
在Istio的架构中,这两个模块的分工非常的清晰,体现在架构上也是经纬分明: Mixer,Pilot和Auth这三个模块都是Go语言开发,代码托管在Github上,三个仓库分别是 Istio/mixer, Istio/pilot/auth。而Envoy来自Lyft,编程语言是c++ 11,代码托管在Github但不是Istio下。从团队分工看,Google和IBM关注于控制面板中的Mixer,Pilot和Auth,而Lyft继续专注于Envoy。
Istio的这个架构设计,将底层Service Mesh的具体实现,和Istio核心的控制面板拆分开。从而使得Istio可以借助成熟的Envoy快速推出产品,未来如果有更好的Service Mesh方案也方便集成。
Pilot
流量管理
Istio最核心的功能是流量管理,前面我们看到的数据面板,由Envoy组成的服务网格,将整个服务间通讯和入口/出口请求都承载于其上。
使用Istio的流量管理模型,本质上将流量和基础设施扩展解耦,让运维人员通过Pilot指定它们希望流量遵循什么规则,而不是哪些特定的pod/VM应该接收流量。
对这段话的理解, 可以看下图:假定我们原有服务B,部署在Pod1/2/3上,现在我们部署一个新版本在Pod4在,希望实现切5%的流量到新版本。
如果以基础设施为基础实现上述5%的流量切分,则需要通过某些手段将流量切5%到Pod4这个特定的部署单位,实施时就必须和ServiceB的具体部署还有ServiceA访问ServiceB的特定方式紧密联系在一起. 比如如果两个服务之间是用Nginx做反向代理,则需要增加Pod4的IP作为Upstream,并调整Pod1/2/3/4的权重以实现流量切分。
如果使用Istio的流量管理功能, 由于Envoy组成的服务网络完全在Istio的控制之下,因此要实现上述的流量拆分非常简单. 假定原版本为1.0,新版本为2.0,只要通过Polit 给Envoy发送一个规则:2.0版本5%流量,剩下的给1.0。
这种情况下,我们无需关注2.0版本的部署,也无需改动任何技术设置, 更不需要在业务代码中为此提供任何配置支持和代码修改。一切由 Pilot 和智能Envoy代理搞定。
我们还可以玩的更炫一点, 比如根据请求的内容来源将流量发送到特定版本
后面我们会介绍如何从请求中提取出User-Agent这样的属性来配合规则进行流量控制。
Pilot的功能概述
我们在前面有强调说,Envoy在其中扮演的负责搬砖的民工角色,而指挥Envoy工作的民工头就是Pilot模块。
官方文档中对Pilot的功能描述:
Pilot负责收集和验证配置并将其传播到各种Istio组件。它从Mixer和Envoy中抽取环境特定的实现细节,为他们提供独立于底层平台的用户服务的抽象表示。此外,流量管理规则(即通用4层规则和7层HTTP/gRPC路由规则)可以在运行时通过Pilot进行编程。
每个Envoy实例根据其从Pilot获得的信息以及其负载均衡池中的其他实例的定期健康检查来维护负载均衡信息,从而允许其在目标实例之间智能分配流量,同时遵循其指定的路由规则。
Pilot负责在Istio服务网格中部署的Envoy实例的生命周期。
Pilot的架构
下图是Pilot的架构图:
Envoy API负责和Envoy的通讯, 主要是发送服务发现信息和流量控制规则给Envoy
Envoy提供服务发现,负载均衡池和路由表的动态更新的API。这些API将Istio和Envoy的实现解耦。(另外,也使得Linkerd之类的其他服务网络实现得以平滑接管Envoy)
Polit定了一个抽象模型,以从特定平台细节中解耦,为跨平台提供基础
Platform
Adapter则是这个抽象模型的现实实现版本, 用于对接外部的不同平台
最后是 Rules
API,提供接口给外部调用以管理Pilot,包括命令行工具Istioctl以及未来可能出现的第三方管理界面
服务规范和实现
Pilot架构中, 最重要的是Abstract
Model和Platform Adapter,我们详细介绍。
Abstract
Model:是对服务网格中”服务”的规范表示, 即定义在istio中什么是服务,这个规范独立于底层平台。
Platform Adapter:这里有各种平台的实现,目前主要是Kubernetes,另外最新的0.2版本的代码中出现了Consul和Eureka。
Pilot功能
基于上述的架构设计,Pilot提供以下重要功能:
请求路由
服务发现和负载均衡
故障处理
故障注入
规则配置
Mixer
Mixer翻译成中文是混音器, 下面是它的图标:
功能概括:Mixer负责在服务网格上执行访问控制和使用策略,并收集Envoy代理和其他服务的遥测数据。
Mixer的设计背景
我们的系统通常会基于大量的基础设施而构建,这些基础设施的后端服务为业务服务提供各种支持功能。包括访问控制系统,遥测捕获系统,配额执行系统,计费系统等。在传统设计中, 服务直接与这些后端系统集成,容易产生硬耦合。在Istio中,为了避免应用程序的微服务和基础设施的后端服务之间的耦合,提供了 Mixer 作为两者的通用中介层:
Mixer 设计将策略决策从应用层移出并用配置替代,并在运维人员控制下。应用程序代码不再将应用程序代码与特定后端集成在一起,而是与Mixer进行相当简单的集成,然后 Mixer 负责与后端系统连接。
特别提醒: Mixer不是为了在基础设施后端之上创建一个抽象层或者可移植性层。也不是试图定义一个通用的Logging API,通用的Metric API,通用的计费API等等。
Mixer的设计目标是减少业务系统的复杂性,将策略逻辑从业务的微服务的代码转移到Mixer中, 并且改为让运维人员控制。
Mixer的功能
Mixer 提供三个核心功能:
前提条件检查。允许服务在响应来自服务消费者的传入请求之前验证一些前提条件。前提条件包括认证,黑白名单,ACL检查等等。
配额管理。使服务能够在多个维度上分配和释放配额。典型例子如限速。
遥测报告。使服务能够上报日志和监控。
在Istio内,Envoy重度依赖Mixer。
Mixer的适配器
Mixer是高度模块化和可扩展的组件。其中一个关键功能是抽象出不同策略和遥测后端系统的细节,允许Envoy和基于Istio的服务与这些后端无关,从而保持他们的可移植。
Mixer在处理不同基础设施后端的灵活性是通过使用通用插件模型实现的。单个的插件被称为适配器,它们允许Mixer与不同的基础设施后端连接,这些后台可提供核心功能,例如日志,监控,配额,ACL检查等。适配器使Mixer能够暴露一致的API,与使用的后端无关。在运行时通过配置确定确切的适配器套件,并且可以轻松指向新的或定制的基础设施后端。
Istio-Auth
Istio-Auth提供强大的服务到服务和终端用户认证,使用交互TLS,内置身份和凭据管理。它可用于升级服务网格中的未加密流量,并为运维人员提供基于服务身份而不是网络控制实施策略的能力。
Istio的未来版本将增加细粒度的访问控制和审计,以使用各种访问控制机制(包括基于属性和角色的访问控制以及授权钩子)来控制和监视访问您的服务,API或资源的人员。
结论:
不是ESB过时,而是你的集中式ESB过时了,分布式ESB
Service Mesh 开启一个微服务的一个新的架构实现模式。Istio 可以充当一个ESB的地位。Istio 超越 spring cloud和dubbo 等传统开发框架之处,就在于不仅仅带来了远超这些框架所能提供的功能,而且也不需要应用程序为此做大量的改动,开发人员也不必为上面的功能实现进行大量的知识储备。