字节跳动开源微服务中间件 CloudWeGo
据介绍,作为项目维护方,字节跳动基础架构团队已推进项目以 CloudWeGo 开源库为主进行迭代,未来团队将坚持内外维护一套代码,统一迭代演进,并逐步分享更多内部微服务佳实践
CloudWeGo 批开源了四个项目,以 RPC 框架 Kitex 和网络库 Netpoll 为主。
Kitex
Kitex 是一个 Golang 微服务 RPC 框架,具有高性能、强可扩展的特点。
字节跳动使用 Golang 作为主要业务开发语言。早在 2016 年,基础架构团队就已经开始基于 Golang 开发内部框架 Kite,并在 2019 年围绕性能和可扩展启动重构,使其能更好地满足业务发展和技术体系演进需求。
2020 年 10 月,Kitex 正式上线。虽然是一个全新的框架,但经过一年的线上应用,目前字节跳动内部已有超过 50% 的 Golang 微服务迁移到了 Kitex。
下面是 Kitex 的一些特性:
高性能:Kitex 默认集成自研网络库 Netpoll 作为网络传输模块,性能相较使用 go net 有显著优势;除了网络库带来的性能收益,Kitex 对 Thrift 编解码也做了优化,这在之前的性能优化实践文章中有介绍。关于性能数据,可参考 https://g***/cloudwego/kitex-benchmark。
扩展性:Kitex 设计上做了模块划分,提供了较多的扩展接口以及默认的扩展实现,使用者也可以根据需要自行定制扩展。Kitex 未耦合 Netpoll,开发者可选择其他网络库扩展使用。
消息协议:RPC 消息协议默认支持 Thrift、Kitex Protobuf、gRPC。Thrift 支持 Buffered 和 Framed 二进制协议;Kitex Protobuf 是 Kitex 自定义的 Protobuf 消息协议,协议格式类似 Thrift;gRPC 是对 gRPC 消息协议的支持,可以与 gRPC 互通。除此之外,使用者也可以扩展自己的消息协议。
传输协议:传输协议封装消息协议进行 RPC 互通,传输协议可以额外透传元信息,用于服务治理,Kitex 支持的传输协议有 TTHeader、HTTP2。TTHeader 可以和 Thrift、Kitex Protobuf 结合使用;HTTP2 目前主要是结合 gRPC 协议使用,后续也会支持 Thrift。
多消息类型:支持 PingPong、Oneway、双向 Streaming。其中 Oneway 目前只对 Thrift 协议支持,双向 Streaming 只对 gRPC 支持,后续会考虑支持 Thrift 的双向 Streaming。
服务治理:支持服务注册/发现、负载均衡、熔断、限流、重试、监控、链路跟踪、日志、诊断等服务治理模块,大部分均已提供默认扩展,使用者可选择集成。
代码生成工具:Kitex 内置代码生成工具,可支持生成 Thrift、Protobuf 以及脚手架代码。
Netpoll
Netpoll 是字节跳动内部的 Golang 高性能、I/O 非阻塞的网络库,专注于 RPC 场景。
RPC 通常有较重的处理逻辑(业务逻辑、编解码),耗时长,不能像 Redis 一样采用串行处理(必须异步)。而 Go 的标准库 net 设计了 BIO(Blocking I/O) 模式的 API,为了保证异步处理,RPC 框架设计上需要为每个连接都分配一个 goroutine,这在空闲连接较多时,产生大量的空闲 goroutine,增加调度开销。此外,ne***nn 没有提供检查连接活性的 API,很难设计出的连接池,池中的失效连接无法及时清理,复用低效。开源社区目前缺少专注于 RPC 方案的 Go 网络库。类似的项目如:evio、gnet 等,均面向 Redis、Haproxy 这样的场景。
因此 Netpoll 应运而生,它借鉴了 evio 和 Netty 的设计,具有出色的性能,更适用于微服务架构。
Thriftgo
Thriftgo 是 Go 语言实现的 Thrift IDL 解析和代码生成器,支持完善的 Thrift IDL 语法和语义检查,相较 Apache Thrift 的 Golang 生成代码,Thriftgo 做了一些问题修复且支持插件机制,用户可根据需求自定义生成代码。
Kitex 的代码生成工具就是 Thriftgo 的插件,CloudWeGo 近期也会开源另一个 Thriftgo 的插件 thrift-gen-validator,支持 IDL Validator,用于字段值校验,解决开发者需要自行实现代码校验逻辑的负担,弥补 Thrift 缺失的能力。
Thriftgo 目前虽然仅支持生成 Golang Thrift 代码,但其定 位是可支持各语言的 Thrift 代码生成,未来如果有需求,我们会考虑生成其他语言的代码。同时我们也会尝试将其回馈至 Apache Thrift 社区。
Netpoll-http2
Netpoll-http2 基于 Golang 标准库 g***/x/net/http2 的源码替换 go net 为 Netpoll,目前用于 Kitex 对 gRPC 协议的支持,对 HTTP2 有需求的外部开发者也可以使用此库。
前面提到字节跳动会坚持内外维护一套代码,为了遵守长期投入承诺,其基础架构团队已经将与内部生态没有耦合的项目,如 Netpoll,直接迁移到 CloudWeGo 开源库,并将内部依赖调整为开源库。
对于需要集成治理能力融入微服务体系的 Kitex,他们基于其扩展性,对内外部代码做了拆分,把 Kitex 的核心代码迁移到开源库,内部库封装一层壳保证内部用户无感知升级,而集成内部治理特性的模块则作为 Kitex 的扩展保留在内部库。字节跳动基础架构团队表示,未来也会持续把已经在内部经过稳定性验证的新特性,迁移到开源库。
谈到 CloudWeGo 的未来规划,字节跳动基础架构团队表示:“CloudWeGo 不仅仅是一个开源项目,它也是一个真实的超大规模企业级实践项目。通过开源,我们希望 CloudWeGo 能丰富云原生社区的 Golang 工具体系,为更多开发者和企业搭建云原生化的大规模分布式系统,提供一种现代的、资源的的技术方案。”
未来他们会进一步推动 CloudWeGo 走向完善:
继续开源其他内部项目。开源更多字节跳动常用 Golang 项目,如 HTTP 框架 Hertz、基于共享内存的 IPC 通信库 ShmIPC 等,为开发者提供更多场景的微服务需求支持。
逐步开源经验证的、稳定的特性。CloudWeGo 的主要项目均为字节内部微服务提供支持,许多新特性仍在内部验证,相对成熟后会逐步开源,如对 ShmIPC 的集成、无序列化、无生成代码的支持等。
结合内外部用户需求,持续迭代。项目开源后会根据开发者需求开展迭代。例如近一个月来,团队收到了来自开发者的大量关于 Protobuf 的诉求,为了提供良好的支持,他们已经在筹备开展 Kitex 对 Protobuf 支持的性能优化。
CloudWeGo 批开源了四个项目,以 RPC 框架 Kitex 和网络库 Netpoll 为主。
Kitex
Kitex 是一个 Golang 微服务 RPC 框架,具有高性能、强可扩展的特点。
字节跳动使用 Golang 作为主要业务开发语言。早在 2016 年,基础架构团队就已经开始基于 Golang 开发内部框架 Kite,并在 2019 年围绕性能和可扩展启动重构,使其能更好地满足业务发展和技术体系演进需求。
2020 年 10 月,Kitex 正式上线。虽然是一个全新的框架,但经过一年的线上应用,目前字节跳动内部已有超过 50% 的 Golang 微服务迁移到了 Kitex。
下面是 Kitex 的一些特性:
高性能:Kitex 默认集成自研网络库 Netpoll 作为网络传输模块,性能相较使用 go net 有显著优势;除了网络库带来的性能收益,Kitex 对 Thrift 编解码也做了优化,这在之前的性能优化实践文章中有介绍。关于性能数据,可参考 https://g***/cloudwego/kitex-benchmark。
扩展性:Kitex 设计上做了模块划分,提供了较多的扩展接口以及默认的扩展实现,使用者也可以根据需要自行定制扩展。Kitex 未耦合 Netpoll,开发者可选择其他网络库扩展使用。
消息协议:RPC 消息协议默认支持 Thrift、Kitex Protobuf、gRPC。Thrift 支持 Buffered 和 Framed 二进制协议;Kitex Protobuf 是 Kitex 自定义的 Protobuf 消息协议,协议格式类似 Thrift;gRPC 是对 gRPC 消息协议的支持,可以与 gRPC 互通。除此之外,使用者也可以扩展自己的消息协议。
传输协议:传输协议封装消息协议进行 RPC 互通,传输协议可以额外透传元信息,用于服务治理,Kitex 支持的传输协议有 TTHeader、HTTP2。TTHeader 可以和 Thrift、Kitex Protobuf 结合使用;HTTP2 目前主要是结合 gRPC 协议使用,后续也会支持 Thrift。
多消息类型:支持 PingPong、Oneway、双向 Streaming。其中 Oneway 目前只对 Thrift 协议支持,双向 Streaming 只对 gRPC 支持,后续会考虑支持 Thrift 的双向 Streaming。
服务治理:支持服务注册/发现、负载均衡、熔断、限流、重试、监控、链路跟踪、日志、诊断等服务治理模块,大部分均已提供默认扩展,使用者可选择集成。
代码生成工具:Kitex 内置代码生成工具,可支持生成 Thrift、Protobuf 以及脚手架代码。
Netpoll
Netpoll 是字节跳动内部的 Golang 高性能、I/O 非阻塞的网络库,专注于 RPC 场景。
RPC 通常有较重的处理逻辑(业务逻辑、编解码),耗时长,不能像 Redis 一样采用串行处理(必须异步)。而 Go 的标准库 net 设计了 BIO(Blocking I/O) 模式的 API,为了保证异步处理,RPC 框架设计上需要为每个连接都分配一个 goroutine,这在空闲连接较多时,产生大量的空闲 goroutine,增加调度开销。此外,ne***nn 没有提供检查连接活性的 API,很难设计出的连接池,池中的失效连接无法及时清理,复用低效。开源社区目前缺少专注于 RPC 方案的 Go 网络库。类似的项目如:evio、gnet 等,均面向 Redis、Haproxy 这样的场景。
因此 Netpoll 应运而生,它借鉴了 evio 和 Netty 的设计,具有出色的性能,更适用于微服务架构。
Thriftgo
Thriftgo 是 Go 语言实现的 Thrift IDL 解析和代码生成器,支持完善的 Thrift IDL 语法和语义检查,相较 Apache Thrift 的 Golang 生成代码,Thriftgo 做了一些问题修复且支持插件机制,用户可根据需求自定义生成代码。
Kitex 的代码生成工具就是 Thriftgo 的插件,CloudWeGo 近期也会开源另一个 Thriftgo 的插件 thrift-gen-validator,支持 IDL Validator,用于字段值校验,解决开发者需要自行实现代码校验逻辑的负担,弥补 Thrift 缺失的能力。
Thriftgo 目前虽然仅支持生成 Golang Thrift 代码,但其定 位是可支持各语言的 Thrift 代码生成,未来如果有需求,我们会考虑生成其他语言的代码。同时我们也会尝试将其回馈至 Apache Thrift 社区。
Netpoll-http2
Netpoll-http2 基于 Golang 标准库 g***/x/net/http2 的源码替换 go net 为 Netpoll,目前用于 Kitex 对 gRPC 协议的支持,对 HTTP2 有需求的外部开发者也可以使用此库。
前面提到字节跳动会坚持内外维护一套代码,为了遵守长期投入承诺,其基础架构团队已经将与内部生态没有耦合的项目,如 Netpoll,直接迁移到 CloudWeGo 开源库,并将内部依赖调整为开源库。
对于需要集成治理能力融入微服务体系的 Kitex,他们基于其扩展性,对内外部代码做了拆分,把 Kitex 的核心代码迁移到开源库,内部库封装一层壳保证内部用户无感知升级,而集成内部治理特性的模块则作为 Kitex 的扩展保留在内部库。字节跳动基础架构团队表示,未来也会持续把已经在内部经过稳定性验证的新特性,迁移到开源库。
谈到 CloudWeGo 的未来规划,字节跳动基础架构团队表示:“CloudWeGo 不仅仅是一个开源项目,它也是一个真实的超大规模企业级实践项目。通过开源,我们希望 CloudWeGo 能丰富云原生社区的 Golang 工具体系,为更多开发者和企业搭建云原生化的大规模分布式系统,提供一种现代的、资源的的技术方案。”
未来他们会进一步推动 CloudWeGo 走向完善:
继续开源其他内部项目。开源更多字节跳动常用 Golang 项目,如 HTTP 框架 Hertz、基于共享内存的 IPC 通信库 ShmIPC 等,为开发者提供更多场景的微服务需求支持。
逐步开源经验证的、稳定的特性。CloudWeGo 的主要项目均为字节内部微服务提供支持,许多新特性仍在内部验证,相对成熟后会逐步开源,如对 ShmIPC 的集成、无序列化、无生成代码的支持等。
结合内外部用户需求,持续迭代。项目开源后会根据开发者需求开展迭代。例如近一个月来,团队收到了来自开发者的大量关于 Protobuf 的诉求,为了提供良好的支持,他们已经在筹备开展 Kitex 对 Protobuf 支持的性能优化。