CloudWeGo

简介

CloudWeGo是一套由字节跳动基础架构服务框架团队开源的、可以快速构建企业级云原生微服务架构的中间件集合。

CloudWeGo项目的共同特点是高性能、高扩展性、高可靠,专注于微服务通信与治理

CloudWeGo包括Kitex,Hertz、Volo、Netpoll、Monoio、Sonic等多个重点子项目,涵盖Go与Rust开发语言,上至框架下至网络库、编码库、序列化库均是自研,各个项目既可以独立使用也可以搭配使用,并且围绕这些项目,构建了完整的上下游生态。

RPC

RPC (Remote Procedure Call) ,即远程过程调用。通俗来讲,就是调用远端服务的某个方法,并获取到对应的响应。RPC 本质上定义了一种通信的流程,而具体的实现技术没有约束,核心需要解决的问题为序列化网络通信。如可以通过 gob/json/pb/thrift 来序列化和反序列化消息内容,通过 socket/http 来进行网络通信。只要客户端与服务端在这两方面达成共识,能够做到消息正确的解析接口即可。

一般来说,RPC 框架包括了代码生成、序列化、网络通讯等,主流的微服务框架也会提供服务治理相关的能力,比如服务发现、负载均衡、熔断等等。

RPC调用流程

一次rpc调用包括以下基本流程,分为客户端和服务端俩个部分:

  1. 客户端:构造请求参数,发起调用
  2. 客户端:通过服务发现、负载均衡等得到服务端的实例地址,并建立连接
  3. 请求参数序列化为二进制
  4. 通过网络将数据发送给服务端

  1. 服务端:服务端接受数据
  2. 服务端:反序列化出请求参数
  3. 服务度:hander处理请求并返回响应结果
  4. 服务度:将响应结果序列化成二进制数据
  5. 服务端:通过网络将数据返回给客户端

  1. 客户端:接收数据
  2. 客户端:反序列化结果
  3. 客户端:得到调用结果

其中步骤2中包含的流程成为服务治理,通常包括但不限于服务发现、负载均衡、ACL、熔断、限流等等功能。这些功能是其他组件提供的,并不是Thrift框架所具有的功能。

RPC服务开发流程

例如基于Thrift的RPC服务开发,通常包括如下过程

  1. 编写IDL,定义服务(Service)接口。
  2. 使用thrift(或者等价的生成代码根据,如kitex等)生成客户端、服务端的支持代码
  3. 服务端开发者编写handler,即请求处理的逻辑
  4. 服务端开发者运行服务监听端口,处理请求
  5. 客户端开发者编写客户端程序,经过服务发现连接上服务端程序,发起请求并接收响应。

IDL

IDL全称是Interface Definition Language,接口定义语言。

如果我们要使用RPC进行调用,就需要知道对方的接口是什么,需要传什么参数,同事也需要知道返回值是什么样的,就好比俩个人之间交流,需要保证再说的是同一个语言、同一件事。IDL就是为了解决这样的问题,通过IDL来约定双方的协议,就像在写代码的时候需要调用某个函数,我们需要知道签名一样。

对于RPC框架,IDL不仅作为借口描述语言,还会根据IDL文件生成指定语言的接口定义模块,这样极大简化了开发工作。服务调用方(服务端)需要做的变为IDL->使用代码生成工具生成代码->实现接口;服务调用方(客户端)只需根据服务提供方(服务端)提供的IDL生成代码后进行调用。这当中还有服务发现负载均衡等问题,但不属于IDL范畴,故不展开介绍。

Kitex 默认支持 thriftproto3 两种 IDL。本文简单介绍 Thrift IDL 语法,proto3 语法可参考:Language Guide(proto3)

基本语法

基本类型

Thrift IDL有以下几种基本类型

  • bool: 布尔型
  • byte: 有符号字节
  • i8: 8位有符号整型(低版本不支持)
  • i16: 16位有符号整型
  • i32: 32位有符号整型
  • i64: 64位有符号整型
  • double: 64位浮点型
  • string: 字符串(编码方式未知或二进制字符串)

注意Thrift IDL没有无符号的整数类型。因为许多编程语言中没有原生的无符号整数类型

  • binary: 表示无编码要求的 byte 二进制数组。因此是字节数组情况下(比如 json/pb 序列化后数据在 thrift rpc 间传输)请使用 binary 类型,不要使用 string 类型;

    • Golang 的实现 string/binary 都使用 string 类型进行存储,string 底层只是字节数组不保证是 UTF-8 编码的,可能与其他语言的行为不一致。

特殊类型

Thrift 提供的容器是强类型容器,映射到大多数编程语言中常用的容器类型。具体包括以下三种容器:

  • list< t1 >: 元素类型为 t1 的有序列表,允许元素重复。Translates to an STL vector, Java ArrayList, native arrays in scripting languages, etc.
  • set< t1 >: 元素类型为 t1 的无序表,不允许元素重复。
  • map<t1,t2>: 键类型为 t1,值类型为 t2 的 map。

Gertz

概览 | CloudWeGo

Hertz[həːts] 是一个 Golang 微服务 HTTP 框架,在设计之初参考了其他开源框架 fasthttpginecho 的优势, 并结合字节跳动内部的需求,使其具有高易用性、高性能、高扩展性等特点,目前在字节跳动内部已广泛使用。 如今越来越多的微服务选择使用 Golang,如果对微服务性能有要求,又希望框架能够充分满足内部的可定制化需求,Hertz 会是一个不错的选择。

Last modification:April 12, 2024
如果觉得我的文章对你有用,请随意赞赏