感谢 DockOne 社区组织的这次技术分享, 感谢各位对微服务感兴趣的技术朋友的参与.
先自我介绍一下, 我是单家骏(英文名 andrew), 腾讯中间件的研发. 腾讯云当前为公有云及企业客户提供微服务平台产品 TSF. 我主要负责中间件后台技术开发, 主要针对微服务框架部分.
今天和大家分享的话题是腾讯云 TSF 微服务平台以及 ServiceMesh 技术实践经验.
先说一下背景.
在当今信息爆炸的时代, 各行业的业务量都在爆发性增长, 对于传统企业来说, 增长的业务量往往对 IT 系统带来不少挑战, 出现了如应用模块耦合, 业务代码滚雪球式增长, 项目迭代时间长, 单模块故障影响全局等问题. 因此, 很多传统企业希望转型微服务架构来解决上面的问题. 而微服务框架自身的复杂性及架构多样性, 则为该架构的选型及构建增加了入门门槛. 因此, 希望 TSF 对微服务的摸索经验和技术实践能为众多企业构建微服务框架发挥一定的借鉴作用.
首先我们来聊聊微服务框架的技术演进
微服务架构来源于分布式架构, 是分布式系统在云计算时代产物, 一个或多个微服务可以组成一个大型复杂软件应用, 微服务之间是松耦合的架构, 可以独立部署, 升级. 基于微服务的系统可提供高级别的系统水平扩展能力.
在微服务架构的实现中, 为提升效率和降低门槛, 应用开发者会基于微服务框架来实现微服务. 微服务框架一定程度上为使用者屏蔽了底层网络的复杂性及分布式场景下的不确定性. 通过 API/SDK 的方式提供服务注册发现, 服务 RPC 通信, 服务配置管理, 服务负载均衡, 路由限流, 容错, 服务监控及治理, 服务发布及升级等通用能力.
第一代微服务框架(准确来说应该属于分布式 RPC 通信框架), 分层架构如下:
代表是 COBRA 及 webServices, 通过协议描述文件 (IDL/WSDL) 约定双方的通信接口, 应用通过 SDK 来进行服务通信. 但是, 应用开发者需要写大量复杂及重复的代码来解决分布式场景下的服务发现, 失败重试, 过载熔断等问题.
为了解决第一代框架中遇到的问题, 出现了第二代微服务框架, 分层架构如下:
典型的产品是 SpringCloud, Finagle, dubbox 等. 开发人员通过集成相应的类库 SDK, 通过配置以及调用 SDK 接口的方式来进行微服务的开发. 由于 Java 语言的便捷以及 Spring 框架的普及, 当前这种模式的微服务框架是业界使用最广泛的微服务框架. 传统行业中, 对于那种本身是基于 Java&Spring 开发的应用, 或者新开发的应用, 基本上都首选采用该微服务框架来进行改造.
但是第二代框架也不能解决所有问题, 对于一些类似传统银行, 敏感机关, 或者小型企业的行业客户, 其应用的特点具备跨语言, 应用改造流程复杂, 线上节点替换升级风险大, ISV 技术积累较浅的特质. 在这种情况下, 往往难以说服他们使用框架 SDK 进行改造.
在这种背景下, 催生了下一代微服务架构 SeviceMesh, 一种基于外置 sidecar 模式的微服务框架. 其架构特点是把微服务框架的能力移到了微服务外部, 作为独立的 sidecar 进程来提供. 微服务之间通过 sidecar 透明代理的方式来进行通信. 使得服务开发者只需要聚焦业务本身, 服务可随意跨语言实现. 而在升级过程中, sidecar 可以独立升级, 无需与微服务进行联动替换. 从而解决了第二代框架所遗留的问题.
典型的开源产品有 spring cloud sidecar(无独立控制面)以及 istio/envoy(带独立控制面), 分层架构如下:
接下来我们针对 TSF 中使用的 Spring Cloud 及 ServiceMesh 的能力做一个展开的分享.
当前腾讯云的 TSF 的微服务能力主要包括 2 部分:
1. 服务框架层包括嵌入式 SDK 以及 ServiceMesh.
2. 服务生命周期管理层包括自研的 PaaS 以及治理运维平台(不在本次分享范围之内)
嵌入式 SDK 主要是基于 Spring Cloud 来实现. Spring Cloud 是业界覆盖量比较高的一个优秀的开源微服务框架, 其特点是基于 springboot 微容器能力的基础上, 融合了 netflix, hashicorp 等组织所开源的组件, 形成的一个配置驱动, 能力相对完备, 高度可扩展的服务框架. 如下为其组件与微服务框架能力的对应表:
框架能力 Spring Cloud 组件
服务注册发现 spring-cloud-eureka,spring-cloud-consul, spring-cloud-zookeeper
服务 RPC 通信 spring-cloud-feign,spring-webmvc,spring-cloud-zuul
服务配置管理 spring-cloud-config
服务路由, 负载均衡 spring-cloud-ribbon
服务容错(限流, 隔离, 熔断, 重试) spring-cloud-hystrix
服务安全 spring-security
服务监控及治理 spring-cloud-sleuth 提供调用链日志采集及上报能力, 可依赖 zipkin 等做分析及查看
服务发布及升级 spring-cloud 本身能力不具备, 可通过 spring-cloud-kubernetes 对接外部 paas 平台如 kubernetes 提供
由表格可以看出, spring cloud 的核心能力在于微服务交互本身, 但是其存在以下的问题:
1. 缺乏复杂的服务治理能力(服务降级, 服务监控, 动态扩缩容, 灰度发布), 在一些可靠性, 性能要求较高的场景下, 也缺少相应的原生能力支撑(如异地多活, 服务本地缓存, 四层协议通信)
2. 在一些生产态的问题定位定界上, 由于 spring cloud 自身打印的日志以 debug 为主, 但是为了性能考虑, 现网往往不会开启 debug 日志. 因此当出现服务丢失等问题时, 最常见的做法是依赖服务治理平台集成外部的 APM 框架来进行应用内部监控.
因此, 大家在基于 spring cloud 作为服务框架的实践过程中, 要注意规避或解决上面所提及的问题. 而 TSF 对 spring cloud 通过自研及集成开源的方式, 补齐了 spring cloud 的所缺失的短板, 提供了完善的含 paas 及运维治理能力的服务框架, 但由于篇幅关系今天不展开讨论.
接下来我们重点讲讲 ServiceMesh 的实现.
TSF 服务框架的 ServiceMesh 主要是有 2 类实现.
第一类 ServiceMesh 实现是无独立控制面的全功能 sidecar, 主要适用于有一定的研发能力, 且对定制化要求较高的企业客户. TSF 主要是基于 Spring Cloud Sidecar 能力来实现全功能 sidecar.Spring Cloud Sidecar 的灵感来源于 Netfix 的 Prana ( https://github.com/Netflix/Pran a), 这个也是 Spring Cloud 与 ServiceMesh 融合的重要手段. 其主要工作流程如下图所示:
每个服务节点上会部署一个 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 版本.
3. 通过调研 istio 代码, 发现通过一定程度的定制及扩展, 可以使得 istio 与 kubernetes 成功解耦.
经过选型后, 我们 mesh 产品架构如下:
Mesh 涉及的部件所提供的功能如下:
istio-Pilot:ServiceMesh 的大脑, 对接注册中心与配置中心, 通过不同的接口给数据面节点提供服务调用所需要的全部规则及信息(包括 envoy 的内部监听及转发规则, 集群服务信息, 服务路由规则, 负载均衡规则, 服务实例信息等), 所依赖的控制接口描述可参考: https://github.com/envoyproxy/ ... pi/v2 https://github.com/envoyproxy/data-plane-api/tree/master/envoy/api/v2
Istio-Mixer: 提供了一套 attribute 处理框架, 可供用户去定制服务权限控制, 服务 quota 限流, 调用统计信息上报及采集分析的能力.
Istio-CA: 主要是安全相关的. 提供证书的更新, 密钥集中管理下发, RBAC 权限模型的更新及维护等能力.
Pilot-agent: 提供环境初始化, 服务注册, envoy 进程监控的能力.
Envoy: 提供服务的透明代理能力, 可以根据控制面下发的控制信息进行消息的投递. 当前支持的协议包括 HTTP, HTTP2, GRPC.Envoy 本身提供 listener 接口供自定义私有协议.
下面通过一个例子讲解一下 ServiceMesh 内部如何进行消息路由:
1. 服务 A 通过 http://<targetServiceNam http:// 2.A 节点的流量接管能力将该报文接管到本节点的 envoy 进程. 3.envoy 进程通过 Pilot 下发的控制信息(该控制信息的分类及运算比较复杂, 鉴于篇幅关系不详细展开, 后续有机会再单独开篇介绍), 经过一系列的负载均衡计算及权限检查, 确定了 B 服务的目标实例节点, 将信息投递给该节点. 4.B 节点收到消息后, 流量接管能力将消息接管进 envoy.envoy 通过 quota 限流策略检查是否已经达到上限, 检查通过后, 则根据 Pilot 下发的内部路由规则, 路由给节点内的服务实例. 5. 服务实例收到请求后, 进行业务逻辑的处理. 最后, 分享下 ServiceMesh 在使用过程中所遇到的待改进点以及思路. 当前 ServiceMesh 在推广过程中, 遇到的最大的障碍实际上还是 istio 未有商用版本的问题. 不过其实从 isito 官网可以了解到, 当前 istio 大部分核心能力已经是 beta 或者 stable 状态 ( https://istio.io/about/feature-stages.htm l) 因此在商用前只要能够仔细评估涉及的能力范围, 原则上不会出现较大的问题. 其他潜在问题的待改进思路如下: 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 是一个技术栈相当深的系统, 在不同业务场景下, 所面对的挑战以及所需要的底层技术并非今天的分享就能够介绍全面的. 也欢迎对这个方向感兴趣的朋友多和我们交流.. 大家加我微信(danjiajun003) 由于本人学识有限, 所谈及的内容难免有疏漏之处, 还请各位朋友不吝指正. 谢谢! Q: 感谢分享, 请问目前 TSF 的集群规模大概是多大, service mesh 从选型到落地大概用了多少人月? A: 公司内部万级的集群规模, servicemesh 落地大概 20 人月 Q: 请问你们微服务与 k8s 的关系是怎么样的? 下层跑的是 k8s 容器吗? A:k8s 原则上是属于 PaaS 平台, PaaS 平台是负责服务的生命周期管理以及伸缩运维等能力. 而我们微服务框架本身实际上更多是针对服务调用以及治理方面, 其架构是与 PaaS 解耦, 并且可以对接不同的 PaaS 平台(包括 k8s), 我们下层支持容器及虚拟机 Q: 请问一下 tsf 如何融合 spring cloud 和 service mesh? A:TSF 通过 3 种方式融合: 一方面我们有一部分 serviceMesh 方案基于 spring cloud 实现; 二方面, 是统一服务模型与配置模型; 三方面, 是体验统一, 就是服务的部署 / 升级及运维的体验是一致 Q: 咨询个问题: 引入 mesh 之后, 会额外多一跳, 这多一跳带来的性能损失, TSF 是如何找回来的? A: 其实很多团队会纠结引入 mesh 后多了的那 1 跳的性能损失, 其实经过我们验证, 一方面 envoy 性能极高, 媲美 nginx; 二是这一跳的损耗, 实际上与业务处理时延有比较大的关系, 如果业务处理时延在 30 毫秒以上, 那么这一跳带来的损耗实际上可以控制在可控范围内(具体要看机器性能) Q:30ms 时延算很大了. 如果是 2ms 或者 0.xms 是不是必须考虑这个问题了. 也就是说可能得看 envoy 的性能与业务的性能是否接近? A: 根据我们在公有云的测试结果来看是的, 假如业务是属于那种对快速响应而且对时延特别敏感的业务, 确实需要跟进实际的测试模型来评估下具体的性能损耗 Q: 是否考虑一个 sidecar 对应多个微服务的场景? A: 当前已经支持请问 TFS 能支持游戏聊天功能么? 主要是从一个手机终端发送信息到另外一个手机终端, 这样的业务需求服务怎么设计(如果要加新的用户发现服那就算了)? 如何保持一些业务对请求有序要求? Q:. 感谢嘉宾分享, 对于 spring cloud 与 spring cloud sidecar 的区别是什么呢, 对于从 SOA 转型到 spring cloud 有什么好的建议吗? 谢谢 A: spring cloud sidecar 是以 sedecar 方式支持非 java 应用而提供的, 和 spring cloud 没有太直接关系. 具体从 soa 到 spring cloud 转型这个不太好泛泛而谈, 要结合实际情况分析 Q: 集群外的服务是如何调用集群内的服务的? 自己做的反向代理么? 还是用的 zuul? A: TSF 用的是自研的, 性能更高, 稳定性更好. 对于小规模用户可以考虑用 zuul Q: 你好, 根据你的介绍, 你们使用 sidecar 的部署模式, 那在这种情况下, 感觉开发人员在测试过程中也得了解如何通过配置服务本身及 envoy sidecar 实现服务的通讯, 对于 envoy 来说, 开发人员来配置还是比较复杂的, 你们是通过什么方式避免这种复杂的? A: 如果没有一套自动化的管理部署工具, 仅靠人肉支持还是不靠谱的, 定位问题也不方遍, 这也是 TSF 集成 envoy 耗时比较久的一个原因. Q: 请问 TFS 能支持游戏聊天功能么? 主要是从一个手机终端发送信息到另外一个手机终端, 这样的业务需求服务怎么设计(如果要加新的用户发现服那就算了)? 如何保持一些业务对请求有序要求? Q:istio 和 k8s 结合使用时, 服务注册和服务发现是怎么用的? A: isito 本身支持多种服务注册发现机制(包括 k8s, consul, digitalfoundry, ereuka 等), 在启动 istio 时作为参数来配置即可 Q: 请问是否有过使用 grpc 通讯的相关案例或者需要注意的坑? 目前是否能够在生产环境应用? 谢谢 A: 暂时没有发现 envoy-grpc 的坑, 不过 istio 官方对于 grpc 的 feature 状态是 alpha, 所以个人不建议在生产环境的使用 isti 来源: http://www.tuicool.com/articles/QzEVner