DockOne微信分享(一七四):腾讯云TSF微服务平台及ServiceMesh技术实践


【编者的话】在当今信息爆炸的时代,各行业的业务量都在爆发性增长,对于传统企业来说,增长的业务量往往对IT系统带来不少挑战,出现了如应用模块耦合、业务代码滚雪球式增长、项目迭代时间长、单模块故障影响全局等问题。因此,很多传统企业希望转型微服务架构来解决上面的问题。而微服务框架自身的复杂性及架构多样性,则为该架构的选型及构建增加了入门门槛。因此,希望TSF对微服务的摸索经验和技术实践能为众多企业构建微服务框架发挥一定的借鉴作用。

微服务框架的技术演进

微服务架构来源于分布式架构,是分布式系统在云计算时代产物,一个或多个微服务可以组成一个大型复杂软件应用,微服务之间是松耦合的架构、可以独立部署、升级。基于微服务的系统可提供高级别的系统水平扩展能力。

在微服务架构的实现中,为提升效率和降低门槛,应用开发者会基于微服务框架来实现微服务。微服务框架一定程度上为使用者屏蔽了底层网络的复杂性及分布式场景下的不确定性。通过API/SDK的方式提供服务注册发现、服务RPC通信、服务配置管理、服务负载均衡、路由限流、容错、服务监控及治理、服务发布及升级等通用能力。

第一代微服务框架(准确来说应该属于分布式RPC通信框架),分层架构如下:
图片2.png

代表是COBRA及WebServices,通过协议描述文件(IDL/WSDL)约定双方的通信接口,应用通过SDK来进行服务通信。但是,应用开发者需要写大量复杂及重复的代码来解决分布式场景下的服务发现、失败重试、过载熔断等问题。

为了解决第一代框架中遇到的问题,出现了第二代微服务框架,分层架构如下:
图片3.png

典型的产品是SpringCloud、Finagle、Dubbox等。开发人员通过集成相应的类库SDK,通过配置以及调用SDK接口的方式来进行微服务的开发。由于Java语言的便捷以及Spring框架的普及,当前这种模式的微服务框架是业界使用最广泛的微服务框架。传统行业中,对于那种本身是基于Java&Spring开发的应用、或者新开发的应用,基本上都首选采用该微服务框架来进行改造。

但是第二代框架也不能解决所有问题,对于一些类似传统银行、敏感机关、或者小型企业的行业客户,其应用的特点具备跨语言、应用改造流程复杂、线上节点替换升级风险大、ISV技术积累较浅的特质。在这种情况下,往往难以说服他们使用框架SDK进行改造。

在这种背景下,催生了下一代微服务架构SeviceMesh,一种基于外置Sidecar模式的微服务框架。其架构特点是把微服务框架的能力移到了微服务外部,作为独立的Sidecar进程来提供。微服务之间通过Sidecar透明代理的方式来进行通信。使得服务开发者只需要聚焦业务本身,服务可随意跨语言实现。而在升级过程中,Sidecar可以独立升级,无需与微服务进行联动替换。从而解决了第二代框架所遗留的问题。

典型的开源产品有Spring Cloud Sidecar(无独立控制面)以及Istio/Envoy(带独立控制面),分层架构如下:
图片4.png

Spring Cloud及ServiceMesh

接下来我们针对TSF中使用的Spring Cloud及ServiceMesh的能力做一个展开的分享。

当前腾讯云的TSF的微服务能力主要包括2部分:
  1. 服务框架层包括嵌入式SDK以及ServiceMesh。
  2. 服务生命周期管理层包括自研的PaaS以及治理运维平台(不在本次分享范围之内)


嵌入式SDK主要是基于Spring Cloud来实现。Spring Cloud是业界覆盖量比较高的一个优秀的开源微服务框架,其特点是基于Spring Boot微容器能力的基础上,融合了Netflix、HashiCorp等组织所开源的组件,形成的一个配置驱动,能力相对完备,高度可扩展的服务框架。如下为其组件与微服务框架能力的对应表:
微信图片_20180527063032.png

由表格可以看出,Spring Cloud的核心能力在于微服务交互本身,但是其存在以下的问题:
  1. 缺乏复杂的服务治理能力(服务降级、服务监控、动态扩缩容、灰度发布),在一些可靠性、性能要求较高的场景下,也缺少相应的原生能力支撑(如异地多活,服务本地缓存,四层协议通信)。
  2. 在一些生产态的问题定位定界上,由于Spring Cloud自身打印的日志以debug为主,但是为了性能考虑,现网往往不会开启debug日志。因此当出现服务丢失等问题时,最常见的做法是依赖服务治理平台集成外部的APM框架来进行应用内部监控。


因此,大家在基于Spring Cloud作为服务框架的实践过程中,要注意规避或解决上面所提及的问题。而TSF对Spring Cloud通过自研及集成开源的方式,补齐了Spring Cloud的所缺失的短板,提供了完善的含PaaS及运维治理能力的服务框架,但由于篇幅关系今天不展开讨论。

ServiceMesh的实现

接下来我们重点讲讲ServiceMesh的实现。

TSF服务框架的ServiceMesh主要是有2类实现。

第一类ServiceMesh实现是无独立控制面的全功能Sidecar,主要适用于有一定的研发能力,且对定制化要求较高的企业客户。TSF主要是基于Spring Cloud Sidecar能力来实现全功能Sidecar。Spring Cloud Sidecar的灵感来源于Netflix的Prana,这个也是Spring Cloud与ServiceMesh融合的重要手段。其主要工作流程如下图所示:
图片5.png

每个服务节点上会部署一个Sidecar进程,Sidecar根据配置将自身监听地址以及服务名注册到Consul Server。当收到外部请求时,会直接到达Zuul Servlet,此时首先判断请求是否来源于自身节点服务,假如来源于自身节点服务,则直接走本地路由。否则,就走Ribbon流程进行服务路由及转发。Sidecar在运行过程中,会定期调用所代理的服务的健康检查接口,获取服务健康状态并上报Consul Server。这种Sidecar代理+服务的方式,所表现出来的行为,与直接嵌入Spring Cloud SDK模式所表现的行为是一致的。Spring Cloud Sidecar模式的缺点在于对服务的URL有要求(来源于Zuul的约束,必须带有服务名),同时原生的Zuul + Ribbon转发模式的性能较差,缺少独立控制面使得运维成本较高。

第二类实现是带独立控制面的Sidecar,主要适用于对定制化要求不高,但是对性能比较敏感,业务代码改造工作量大,希望低成本运维的企业客户。带独立控制面的Sidecar也是ServiceMesh的业界通用实现。但是开发团队应该如何去实现这种ServiceMesh呢?

实现微服务框架的关键在于开源选型。TSF在Mesh构建初期,业界已经有不少优秀的开源数据面Sidecar产品,如Envoy、Linkrd、nginMesh、Conduit等,而且各有各的亮点和最佳适用场景。但最终数据面选定Envoy的原因在于:
  1. Envoy社区成熟度较高,商用稳定版本面世时间较长。如nginMesh以及Conduit至今仍未有商用版本。
  2. Envoy底层基于C++,性能上优于使用Scala的Linkrd,同时C++与腾讯系的语言体系较吻合。
  3. Envoy在腾讯内部使用相对广泛,稳定性相当高,对于运行态代理,稳定性直接影响交付质量。


而对于数据面的开源选型,则可选范围相对较少,当前控制面集大成者是Istio,业界几乎所有的开源数据平面产品(Conduit除外),都支持对接Istio,但是Istio存在2个问题使得当时在选型上挣扎了一下:
  1. 原生的Istio大部分能力与Kubernetes是强关联的。而TSF则是与P层平台解耦的,框架在设计上需要能够对接多P层平台。
  2. Istio至今未有商用稳定版本,当前最新版本是0.7.1。


最终控制平台仍然选型Istio,原因如下:
  1. Istio拥有极高的社区影响力,开发团队来源于Google和IBM。所基于的xDS(LDS、RDS、CDS、EDS)控制接口规范几乎成为控制面的实际规范。
  2. Istio版本速度较快,今年内极有可能会推出1.0版本。
    图片6.png
  3. 通过调研Istio代码,发现通过一定程度的定制及扩展,可以使得Istio与Kubernetes成功解耦。经过选型后,我们Mesh产品架构如下:
    图片7.png


Mesh涉及的部件所提供的功能如下:

  • Istio-Pilot:ServiceMesh的大脑,对接注册中心与配置中心,通过不同的接口给数据面节点提供服务调用所需要的全部规则及信息(包括Envoy的内部监听及转发规则、集群服务信息、服务路由规则、负载均衡规则、服务实例信息等),所依赖的控制接口描述可参考:https://github.com/envoyproxy/ ... pi/v2

  • Istio-Mixer:提供了一套Attribute处理框架,可供用户去定制服务权限控制、服务Quota限流、调用统计信息上报及采集分析的能力。
  • Istio-CA:主要是安全相关的。提供证书的更新、密钥集中管理下发、RBAC权限模型的更新及维护等能力。
  • Pilot-Agent:提供环境初始化、服务注册、Envoy进程监控的能力。
  • Envoy:提供服务的透明代理能力,可以根据控制面下发的控制信息进行消息的投递。当前支持的协议包括HTTP、HTTP2、GRPC。Envoy本身提供listener接口供自定义私有协议。


ServiceMesh消息路由

下面通过一个例子讲解一下ServiceMesh内部如何进行消息路由:
图片8.png

  1. 服务A通过http://<targetServiceName>:<port>/url的方式对服务B发起REST服务调用。
  2. A节点的流量接管能力将该报文接管到本节点的Envoy进程。
  3. Envoy进程通过Pilot下发的控制信息(该控制信息的分类及运算比较复杂,鉴于篇幅关系不详细展开,后续有机会再单独开篇介绍),经过一系列的负载均衡计算及权限检查,确定了B服务的目标实例节点,将信息投递给该节点。
  4. B节点收到消息后,流量接管能力将消息接管进Envoy。Envoy通过Quota限流策略检查是否已经达到上限,检查通过后,则根据Pilot下发的内部路由规则,路由给节点内的服务实例。
  5. 服务实例收到请求后,进行业务逻辑的处理。


ServiceMesh待改进点以及思路

最后,分享下ServiceMesh在使用过程中所遇到的待改进点以及思路。

当前ServiceMesh在推广过程中,遇到的最大的障碍实际上还是Istio未有商用版本的问题。不过其实从Istio官网可以了解到,当前Istio大部分核心能力已经是beta或者stable状态(https://istio.io/about/feature-stages.html)。

因此在商用前只要能够仔细评估涉及的能力范围,原则上不会出现较大的问题。其他潜在问题的待改进思路如下:

  1. 暴力流量接管:这个也是网上诟病比较多的问题。由于Istio的数据面依赖于针对容器内流量进行全接管,但是对于虚拟机场景下可能不适用,毕竟虚拟机上可能不仅仅只有Mesh的服务。因此,需要考虑细粒度的接管方案。

  2. 全量服务发现问题:Istio是一个集中的控制面,在构建路由数据时,会默认从注册中心获取全量的服务实例数据,一旦服务节点量级上升后,会导致较严重的性能及资源占用问题。因此,定制过程中可以考虑采用服务元数据的方式来减少发现的数据量。

  3. Mixer缓存穿透的问题。由于Envoy在每个请求的发送前以及接受到请求后,都需要往Mixer去查询权限及Quota信息,为提升性能,Envoy会对这些查询结果进行缓存。而由于这些信息是per request的,而且Envoy无法知道会有哪些attributes(key)需要去缓存,从而缓存的总量有可能根据调用时长而呈现不断增长的趋势,引发资源占用问题。因此,在这方面可以适当引入LRU算法来解决。

  4. 多租户隔离的支持。在公有云场景下,用户对隐私和隔离看得非常重要。往往不同用户/租户之间,服务配置、节点信息、控制信息等资源数据是隔离的,互相不可见。但是Istio本身并不支持这种级别的隔离。需要框架集成者去进行扩展。

  5. 自动服务注册能力的支持。Istio并不提供自动服务注册能力(其服务模型依赖Kubernetes的Service),因此,假如需要将Istio脱离Kubernetes运行,首要解决的是自动服务注册的问题。思路是Pilot提供接口获取应用节点服务信息,然后通过通过每个节点部署的Pilot-Agent拉取并注册节点服务实例。


由于ServiceMesh是一个技术栈相当深的系统,在不同业务场景下,所面对的挑战以及所需要的底层技术并非今天的分享就能够介绍全面的。

由于本人学识有限, 所谈及的内容难免有疏漏之处,还请各位朋友不吝指正。谢谢!

Q&A

Q:感谢分享,请问目前TSF的集群规模大概是多大,ServiceMesh从选型到落地大概用了多少人月?

A:公司内部万级的集群规模,ServiceMesh落地大概20人月。
Q:请问你们微服务与Kubernetes的关系是怎么样的?下层跑的是Kubernetes容器吗?

A:Kubernetes原则上是属于PaaS平台,PaaS平台是负责服务的生命周期管理以及伸缩运维等能力。而我们微服务框架本身实际上更多是针对服务调用以及治理方面,其架构是与PaaS解耦,并且可以对接不同的PaaS平台(包括Kubernetes),我们下层支持容器及虚拟机。
Q:请问一下TSF如何融合Spring Cloud和ServiceMesh?

A:TSF通过3种方式融合:一方面我们有一部分ServiceMesh方案基于Spring Cloud实现;二方面,是统一服务模型与配置模型;三方面,是体验统一,就是服务的部署/升级及运维的体验是一致。
Q:引入Mesh之后,会额外多一跳,这多一跳带来的性能损失,TSF是如何找回来的?

A:其实很多团队会纠结引入Mesh后多了的那1跳的性能损失,其实经过我们验证,一方面Envoy性能极高,媲美Nginx;二是这一跳的损耗,实际上与业务处理时延有比较大的关系,如果业务处理时延在30毫秒以上,那么这一跳带来的损耗实际上可以控制在可控范围内(具体要看机器性能)。
Q:30ms时延算很大了。如果是2ms或者0.xms是不是必须考虑这个问题了?也就是说可能得看Envoy的性能与业务的性能是否接近?

A:根据我们在公有云的测试结果来看是的,假如业务是属于那种对快速响应而且对时延特别敏感的业务,确实需要跟进实际的测试模型来评估下具体的性能损耗。
Q:对于Spring Cloud与Spring Cloud Sidecar的区别是什么呢,对于从SOA转型到Spring Cloud有什么好的建议吗?谢谢。

A:Spring Cloud Sidecar是以Sidecar方式支持非Java应用而提供的,和Spring Cloud没有太直接关系。具体从SOA到Spring Cloud转型这个不太好泛泛而谈,要结合实际情况分析。
Q:集群外的服务是如何调用集群内的服务的?自己做的反向代理么?还是用的Zuul?

A:TSF用的是自研的,性能更高,稳定性更好。对于小规模用户可以考虑用Zuul。
Q:你好,根据你的介绍,你们使用Sidecar的部署模式,那在这种情况下,感觉开发人员在测试过程中也得了解如何通过配置服务本身及Envoy Sidecar实现服务的通讯,对于Envoy来说,开发人员来配置还是比较复杂的,你们是通过什么方式避免这种复杂的?

A:如果没有一套自动化的管理部署工具,仅靠人肉支持还是不靠谱的,定位问题也不方遍,这也是TSF集成Envoy耗时比较久的一个原因。
Q:Istio和Kubernetes结合使用时,服务注册和服务发现是怎么用的?

A:Istio本身支持多种服务注册发现机制(包括Kubernetes、Consul、Digital Foundry、Ereuka等),在启动Istio时作为参数来配置即可。
Q:请问是否有过使用gRPC通讯的相关案例或者需要注意的坑?目前是否能够在生产环境应用?

A:暂时没有发现envoy-grpc的坑,不过Istio官方对于gRPC的feature状态是alpha,所以个人不建议在生产环境的使用Istio。
以上内容根据2018年05月15日晚微信群分享内容整理。分享人单家骏,腾讯中间件研发高级工程师,负责腾讯云中间件PaaS以及ServiceMesh的研发与架构。曾在华为公司任职,从事云计算及中间件7年有余。热爱开源、崇尚技术,希望能够使用技术使软件的应用变得简单、高效和美好。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesa,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

0 个评论

要回复文章请先登录注册