乐趣区

关于开源:高性能-RPC-框架-CloudWeGoKitex-内外统一的开源实践

日前,字节跳动技术社区 ByteTech 举办的第七期字节跳动技术沙龙圆满闭幕,本期沙龙以《字节高性能开源微服务框架:CloudWeGo》为主题。在沙龙中,字节跳动字节跳动基础架构服务框架资深研发工程师 杨芮,跟大家分享了《高性能 RPC 框架 Kitex 内外对立的开源实际》,本文依据分享整顿而成。

本文将从以下四个方面介绍 CloudWeGo 高性能 RPC 框架 Kitex 的实际及开源:

  1. 由内至外 – 开源过渡;
  2. 开源一年变更回顾;
  3. 社区共建欠缺生态及企业落地;
  4. 总结和瞻望。

由内至外 – 开源过渡

很多同学可能刚刚理解 CloudWeGo,先介绍一下 CloudWeGo 和 Kitex 的关系。

CloudWeGo 和 Kitex

Kitex 是 CloudWeGo 开源的第一个微服务框架,它是一个 反对多协定的 Golang RPC 框架 ,从网络库、序列化库到框架的实现 根本齐全自研 的。特地地,Kitex 对 gRPC 协定的反对应用了 gRPC 官网的源码,然而咱们对 gRPC 的实现做了 深度且定制的优化,所以 Kitex 反对的 gRPC 协定性能优于 gRPC 官网框架。同时这也是 Kitex 与目前曾经开源的、反对 gRPC 协定的其余 Golang 框架的次要差别。如果用户想应用 gRPC 又对性能有很高的要求,那么 Kitex 框架将会是一个很不错的抉择。

继 Kitex 开源后,往年 CloudWeGo 又陆续开源了 Golang HTTP 框架 Hertz,Rust RPC 框架 Volo,同时围绕这些微服务框架和微服务的一些通用能力,咱们还开源了一些高性能的根底库。对于更多 CloudWeGo 开源的子项目,能够进入 CloudWeGo 官网具体理解。

CloudWeGo 官网:https://www.cloudwego.io/

依据社区同学反馈,在一些开源群里大家会探讨 Kitex 会不会是一个字节跳动的开源 KPI 我的项目呢?它的稳定性、持续性可能失去保障吗?我能够负责任地讲,Kitex 不是一个 KPI 我的项目,它是来自字节跳动外部大规模实际的实在我的项目。在 Kitex 开源后始终保持内外对立,基于内外代码的对立咱们保障了 Kitex 的继续迭代。为了进一步打消大家的顾虑,上面具体介绍一下 Kitex 的诞生和开源历程。

Kitex 倒退历史

2014 年,字节跳动开始引入 Golang。2015 年,字节跳动外部的服务化开启。在 RPC 调用的场景抉择了 Thrift 协定,在外部开始反对 RPC 框架。2016 年,第一个 Golang RPC 框架 Kite 正式公布。通常在一个公司高速倒退的初期,根底能力都是为了疾速反对需要落地,面对的需要场景也较繁多,设计上不会有较多考量,其实这也是正当的,因为摸索阶段并不齐全分明还须要反对哪些场景,过多的思考反而会呈现适度设计的问题。

然而,随着业务场景复杂化,需要也会多样化,而且接入服务及调用量逐年增长,Kite 曾经不足以反对后续的迭代,在线上退役三年多后,2019 年咱们开启了新的我的项目 Kitex,2020 年初公布了正式版本,在 2020 年底字节外部曾经有 1w+ 服务接入 Kitex。

从 2014 年到 2020 年,Golang 曾经是字节跳动外部次要的业务开发语言,应该是业界 Golang 利用最多的公司。咱们的服务框架反对着数万个 Golang 微服务的牢靠通信,通过数量泛滥的微服务和海量流量的验证,咱们曾经有了较为成熟的微服务最佳实际,于是思考将外部的实际开源进来丰盛云原生社区的 Golang 产品体系。在 2021 年,咱们以 CloudWeGo 品牌正式开源了第一个服务框架 Kitex。截至往年 8 月,Kitex 曾经为字节跳动外部 6w+ 的服务提供反对,峰值 QPS 达到上亿级别

大家或者还有疑难,残缺的微服务体系离不开根底的云生态,无论在私有云、公有云,都须要搭建额定的服务以很好地反对微服务的治理,比方治理平台、注册核心、配置核心、监控、链路跟踪、服务网格等,而且还存在一些定制的标准。字节跳动天然也有欠缺的外部服务反对微服务体系,但这些服务短期还无奈开源,那 CloudWeGo 如何内外保护一套代码,对立迭代呢?

对于这个问题,咱们看一下 Kitex 的模块划分。Kitex 的模块分为三个局部:两头是 Kitex 骨干局部 Kitex Core,它定义了框架的层次结构、接口外围逻辑的实现以及接口的默认实现;右边的 Kitex Tool 则是与生成代码相干的实现,咱们的生成代码工具就是编译这个包失去的,其中包含 IDL 的解析、校验、代码生成、插件反对等。不过为了便于用户应用同时提供更敌对的扩大,次要能力也做了拆分作为根底库独立开源,如 Thriftgo、Thrift-validator 插件、Fastpb;左边的 Kitex Byted 是对字节外部根底能力集成的扩大实现,咱们在开始就将外部的能力作为扩大收敛到一个 package 下。

如此,咱们就能够将 Kitex Core 和 Tool 局部开源进来。咱们将代码做了拆分,Kitex 的外围代码和工具局部迁徙到开源库,集成外部扩大的模块作为 Kitex 的扩大保留在外部库,同时外部库封装一层壳保障外部用户能够无感知地降级。

那么 Kitex 的开源就只是代码拆分这么简略吗?显然不是。2021 年 2 月,咱们开始筹备 Kitex 的开源,尽管基于 Kitex 的扩展性,咱们能够与外部基础设施集成的能力解耦,然而 Kitex 依然依赖外部的一些根底库,如果要开源必须先开源根底库的能力。所以咱们首先做了依赖库的梳理,与相干的同学单干首先开源了 bytedance/gopkg 库。这个库由 CloudWeGo 与字节跳动的语言团队单干保护,外面蕴含也了对 Golang 规范库能力的加强,感兴趣的同学能够关注应用。

bytedance/gopkg: https://github.com/bytedance/…

在 gopkg 库开源后,咱们调整代码进行开源适配。2021 年 7 月,Kitex 正式开源,在外部公布中版本应用开源库。但 Kitex 毕竟反对了外部几万的微服务,咱们必须要确保外部服务在这个变更后能够平滑过渡,所以在开源初咱们没有对外官宣,在确认稳定性后,2021 年 9 月,Kitex 正式对外官宣开源

介绍了 Kitex 诞生、开源的历程,心愿可能解除内部同学对于“Kitex 会不会是一个 KPI 我的项目?”的顾虑。

开源的价值

第一局部的最初,简略讲一下开源能为咱们带来的价值。Kitex 不是为了开源而实现的,但它的实现是面向开源的。Kitex 自身是一个通过外部大规模实现的我的项目,咱们心愿 Kitex 开源后能帮忙更多用户在外部疾速搭建微服务,同时开源能让咱们收集更多社区和企业的反馈,也能吸引内部开发者共建,促成 Kitex 面向多元场景反对的演进,丰盛产品能力,而后能在更多场景和企业失去落地,这是一个正向循环,互利共赢的过程。

开源一年变更回顾

框架的掂量指标

在介绍 Kitex 开源一年变更前,先分享一下框架的掂量指标,这是大家在抉择一个框架时要思考的。

  • 扩展性

如果一个框架与外部能力强耦合,就无奈移植到其余平台,或框架的反对场景繁多也无奈进行扩大,这样的框架很难失去内部的应用。

  • 易用性

框架的易用性体现在两个方面。第一是面向 业务开发者 ,如果一个框架在应用过程中须要让用户关注很多框架的细节,那么对研发效率要求很高的团队可能无奈承受。第二是面向 框架的二次开发者,他们须要对框架做一些定制反对,如果框架提供的扩大能力过于宽泛,扩大老本很高,或者可扩大的能力不够多,那么这个框架也是存在局限性的。

  • 性能的丰盛度

尽管基于扩展性能够对框架进行定制,但不是所有开发者都有足够的精力做定制开发,如果框架自身对各种扩大能力提供了不同抉择的反对,对于开发者来说只须要依据本人的基础设施进行组合就能在本人的环境中运行。

  • 高性能

后面三点是初期抉择框架须要重点关注的指标,但随着服务规模和资源耗费变大,性能就成了不容忽视的问题。从长期的角度来说,抉择框架的时候肯定要关注性能,否则后续只能面临框架替换的问题,或者被迫对这个框架做定制保护。

对于以上四点框架的掂量指标,尽管 Kitex 目前还没做到最好,然而这四个因素都是 Kitex 设计和实现中始终在兼顾的,咱们不会顾此失彼。

性能个性

上面就几个开源一年来重要的性能个性进行介绍。

Proxyless

Proxyless 是 Kitex 面向开源场景提供的反对。在 Kitex 开源初期,咱们外部探讨过是否要反对 xDS 对接 Istio,对于内部用户来说,应用 Istio 能够疾速搭建一套根本的微服务架构,解决服务发现、流量路由、配置下发等问题,然而如果应用残缺的 Istio 的解决方案,就要引入 Envoy,这会减少运维老本,而且间接应用官网的 Envoy 计划对性能有损,会引入额定的 CPU 开销且减少提早。如果 Kitex 能间接对接 Istio,既能让用户享受到局部 Istio 的能力,又能够防止 Envoy 带来的性能损失和部署运维老本。然而在开源初期,咱们没有看到很明确的用户诉求,因而没有对此做高优的反对。

起初 gRPC 官网也公布了 Proxyless 的反对,同时 Istio 的官网也将 Proxyless 作为应用 Istio 的一种形式。Kitex 当初也已实现反对,目前次要是对接服务发现,xDS 反对的扩大独自开源到了 kitex-contrib/xds 库中,后续还会欠缺。大家能够依据 README 理解如何应用 Kitex 对接 Istio。

xDS Support: https://github.com/kitex-cont…

JSON 和 Protobuf 泛化调用

反对之前,Kitex 反对了利用在网关场景的 HTTP 泛化,以及反对了利用在一些通用服务场景的 Map 和二进制泛化。开源后,依据用户的需要反馈又新增了 JSON 和 Protobuf 的泛化。

Protobuf 的泛化也是利用在 API 网关的场景。原来的 HTTP 泛化传输的数据格式是 JSON,然而 JSON 的序列化体积大、效率低,对性能有影响,所以很多挪动端的接口抉择应用 Protobuf 传输数据,因而减少了 Protobuf 泛化的反对。

目前 Kitex 的泛化次要针对后端的 Thrift 服务,无论是 Protobuf、Map 还是 JSON,Kitex 都会在调用端联合 IDL 解析,将这些数据映射编码为 Thrift 包发给后端服务。

那么为什么把泛化放在调用端而不是服务端呢?大家宽泛理解的泛化都是服务端对泛化申请做了解析解决,当然调用端也要相应地提供泛化的 Client。然而泛化面向的是通用服务,泛化应用老本其实是比拟高的,它并不适用于一般的 RPC 场景,而通用服务面向的是所有后端的服务,有 Golang/Java/C++/Python/Rust,如果每一种语言框架都反对泛化,老本是十分高的。就算各个语言都对泛化做了反对,框架版本收敛又是一个漫长的过程,对于通用服务来说,对接所有的服务就显得不太事实。综合以上起因,泛化放在调用端反对。

重试能力加强

去年开源时,Kitex 曾经反对了重试性能。之前反对的重试有两类,一个是超时重试,一个是 Backup Request。

对于超时来重试来说,咱们只会对超时这一种异样进行重试,但为了进一步提高申请成功率,用户心愿对其余的异样也进行重试,或者用户可能会定义一些用户申请的状态码,联合用户状态码进行重试,在这种状况下,显然咱们只反对超时重试是不满足用户需要的。基于这个背景,Kitex 新增了指定后果重试,用户能够指定其余异样或指定某一类  Response,框架会联合用户指定的后果进行重试。

其次,用户在配置重试时,如果通过代码配置的形式设置重试,它会对整个 Client 的所有 RPC 办法失效,然而用户心愿针对不同的 RPC 办法利用不同的重试策略,甚至同一个办法也心愿能够采纳不同的重试策略,因为不同链路上发动的同一个办法的申请对指标要求也会不同。比方有些想应用 Backup Request 缩小提早,有些想做异样重试进步成功率,对于这种状况,Kitex 新的版本反对了申请粒度配置重试

下图是应用示例。以申请粒度重试配置为例,比方 RPC 办法是 Mock,那么咱们在发动 RPC 调用的时候,在前面能够配置一个 callopt 指定重试策略,此次申请就会应用这个重试策略。

Thrift Validator

Thrift-gen-validator 是 Thriftgo 的一个工具插件,它能够依据 Thrift IDL 中定义的注解形容束缚给对应的 struct 生成 IsValid() error 办法,校验值的合法性。通常做 RPC 调用的时候,用户可能会对一些字段校验合法性,用户如果间接写这些校验代码,投入的老本会很高。所以咱们就提供了注解反对,只有用户在 IDL 中依据标准定义注解,Kitex 就能够帮忙用户生成校验代码

下图是代码生成的命令和一个 IDL 注解定义示例,在生成代码的时候指定 Thrift Validator 的插件,咱们的插件工具就会解析注解,为用户生成这一套合法性校验的代码。目前咱们也将 Thrift Validator 的性能奉献给了 Apache Thrift。

性能优化

介绍完几个重要的性能个性,再介绍几个在性能上的优化个性。

Thrift 高性能编解码

Frugal 是一个无需生成编解码代码、基于 JIT 的高性能动静 Thrift 编解码器。尽管咱们针对官网 Thrift 编解码曾经做了优化,反对了 FastThrift,这个在咱们开源前公布的优化实际里也有介绍,但咱们心愿能有进一步的性能晋升,参考咱们开源的高性能 JSON 库 Sonic 的设计,实现了 Thrift JIT 编解码器。下图中的表格是 Frugal 联合 Kitex 与 FastThrift 的性能比照。

能够看到在大部分场景 RPC 性能体现都较优。除了性能上的劣势,Frugal 还有另一个劣势是无需生成编解码生成代码。Thrift 的生成代码比 Protobuf 沉重,一个简单的 IDL 代码生成文件能够达到几万行,而这些代码原本对用户来说无需关注,却须要由用户来保护。Frugal 只须要生成构造体代码,不需生成编解码代码,就大大解决了这个问题。

对于如何在 Kitex 中应用 Frugal,能够参考仓库的 Readme。当然用户也能够独自应用 Frugal 作为 Thrift 高性能编解码器,Kitex 后续也会思考默认应用 Frugal。

Frugal: https://github.com/cloudwego/…

Protobuf 高性能编解码

尽管咱们外部次要反对 Thrift,但开源之后咱们发现内部用户对于 Protobuf 或 gRPC 的关注会更多,所以参考 Kitex FastThrift 的优化思路,从新实现了 Protobuf 的生成代码。在 v0.4.0 版本,如果用户应用 Kitex 的工具生成 Protobuf 的代码,就会默认生成 Fastpb 的编解码代码,在发动 RPC 调用的时候,Kitex 也会默认应用 Fastpb。

下图是 Fastpb 与官网 Protobuf 序列化的性能比照,能够看到无论是编码还是解码,在效率和内存调配上,Fastpb 都远远优于官网 Protobuf 序列化库。

gRPC 性能优化

开源初期,咱们对 gRPC 整体稳定性和性能的关注是比拟少的。因为外部应用的场景不是很多。开源后收到了很多内部同学的反馈,所以咱们针对 gRPC 做了一个专项的问题治理以及性能优化。往年中旬咱们曾经把相干的优化正式提交到开源库,在 v0.4.0 版本公布。

Kitex v0.4.0: https://mp.weixin.qq.com/s/ez…

下图中左侧是优化前 Kitex-gRPC 和官网 gRPC 框架对 Unary 申请 的压测吞吐比照,在并发比拟低的状况下,Kitex 的吞吐并不具备劣势,应用 Fastpb 的时候,Kitex 的吞吐体现会好一些,但低并发的吞吐仍然低于官网 gRPC。在优化之后,吞吐对比方右图所示。相比优化前吞吐晋升 46% – 70%,相比官网 gRPC 框架,吞吐高 51% – 70%

下图中右侧是优化后 Unary 申请 的提早比照,在吞吐比官网 gRPC 高出很多的状况下,Kitex 的提早也显著低于官网的 gRPC。同时就 Kitex 本身而言,在优化后提早体现也好了很多。

咱们再看下 Streaming 申请 的压测性能比照,优化前 Streaming 申请的体现同样在低并发的状况下,绝对 gRPC 框架没有劣势。通过优化后,Kitex 吞吐显著高于官网 gRPC,如下图,同时低并发下吞吐高但提早持平,减少并发后能看到提早呈现分叉。所以在性能上,Kitex 反对的 gRPC 协定绝对官网有显著的劣势。

尽管在局部性能上,Kitex 还没有齐全对齐,然而目前曾经能够满足大部分的场景需要,咱们后续也会持续进行性能对齐。

社区共建欠缺生态及企业落地

社区共建的 Kitex 扩大生态

开源后,咱们很快慰失去了很多开发者的关注,坦白说外部团队精力有限,无奈疾速建设起面向内部用户的 Kitex 扩大生态。然而一年以来借助社区的力量,Kitex 在 服务注册 / 发现 可观测性 服务治理 几局部的扩大失去了很多补充,尤其是服务注册 / 发现相干的扩大,目前开源的支流注册核心都已实现对接,尽管在功能丰富度上咱们还有待增强,但联合已有的反对,对于内部用户曾经具备了搭建微服务架构的能力。

衷心感谢积极参与 CloudWeGo 社区建设的同学们!对于 Kitex 相干的生态反对,大家能够进入 Kitex-contrib 理解更多的开源仓库。

Kitex-contrib: https://github.com/kitex-contrib

对接内部企业,帮助落地

咱们开源的初衷是为了助力其余内部企业疾速地搭建企业级的云原生架构。开源后,森马、华兴证券、贪玩游戏、禾多科技先后被动与咱们分割,反馈应用问题、提出需要,确实让咱们发现了一些和外部场景不一样的问题,须要咱们去关注、反对和优化,咱们很开心 Kitex 能在这些企业外部失去利用。在往年 6 月 25 日的 CloudWeGo Meetup 中,森马和华兴证券的研发同学也分享了他们应用 Kitex 的外部实际。

森马:https://mp.weixin.qq.com/s/JA…

华兴证券:https://mp.weixin.qq.com/s/Qq…

除了以上企业,还有一些公司也私下向咱们征询过应用问题,咱们非常感谢这些企业用户的反对,以及向咱们提出的反馈信息。如第一局部所讲,收集社区和企业的反馈能够促成 Kitex 面向多元场景反对的演进,企业用户如果有相干需要,欢送分割咱们。

如何应用 Kitex 与外部基础设施集成

这里再简略介绍下如何应用 Kitex 与大家的外部基础设施集成。以字节外部为例,外部仓库里有开源库中的扩大实现,集成外部的能力,在 bytedSuite 中,咱们针对不同场景对 Kitex 进行初始化。如上面的代码示例,用户只须要在结构 Client 和 Server 时减少一个 option 配置就能够实现集成,不过为了让用户齐全不需关注外部能力的集成,咱们将该配置放在了生成的脚手架代码中,对于配置如何内嵌在生成代码中,后续咱们也会凋谢进去,不便内部的框架二次开发者能以同样的形式为业务开发同学提供集成能力。

总结和瞻望

总结

本次分享次要介绍了以下内容:

  • Kitex 如何放弃内外对立地从外部利用较广的框架转为开源框架;
  • 开源一年以来公布了哪些重要的性能个性,做了哪些性能优化;
  • 借助社区的力量当初 Kitex 的周边生态如何、企业落地状况以及如何应用 Kitex 优雅地集成外部能力。

瞻望

  • 与社区同学共建,继续丰盛社区生态;
  • 联合工程实际,为微服务开发者提供更多便当;
  • 欠缺好 BDThrift 生态,继续优化 Protobuf/gRPC;
  • 更多个性反对或开源,ShmIPC、QUIC、Protobuf 泛化…

以上内容整顿自第七期字节跳动技术沙龙《字节高性能开源微服务框架:CloudWeGo》,获取 讲师 PPT 和回放视频,请关注 CloudWeGo 公众号,并在后盾回复关键词 “一周年”

我的项目地址

GitHub:https://github.com/cloudwego

官网:www.cloudwego.io

退出移动版