国内首个基于 Rust 语言的 RPC 框架 — Volo 正式开源!

Posted CloudWeGo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了国内首个基于 Rust 语言的 RPC 框架 — Volo 正式开源!相关的知识,希望对你有一定的参考价值。

Volo 是字节跳动服务框架团队研发的轻量级高性能可扩展性强易用性好的 Rust RPC 框架,使用了 Rust 最新的 GAT 和 TAIT 特性。

在字节内部,Volo 已经落地多个业务和基础组件,并且取得了超预期的性能收益(与 Go 版本对比,不那么公平)。

Volo 与其它 CloudWeGo 开源项目一样,坚持内外维护一套代码,为开源使用提供了强有力的保障。同时,我们观察到 Rust 开源社区在 RPC 框架这块还比较薄弱,Volo 的开源希望能为社区的完善贡献一份力量,同时也能完善 CloudWeGo 生态矩阵,为追求性能、安全性和最新技术的开发者、企业以及 Rustaceans 开发 RPC 微服务、搭建云原生分布式系统提供强有力的支持。

本文会为大家简单介绍 Volo 及其相关生态,并为大家提供一个简单的 Rust 与 Go 的选型建议。

01 项目缘起

其实 Volo 的创始成员来自于 Kitex 团队(CloudWeGo 开源的 Go RPC 框架),当时我们在 Go 上做了非常深度的性能优化,也因此深刻感受到了在 Go 上做性能优化所面临的阻碍。因此,我们选择了 Rust,期望能够给需求极致性能、安全和指令级掌控能力的业务一个合适的选择。而 RPC 框架是分布式系统中重要的组成部分,Volo 就这么诞生了。

02 特性

高性能

Rust 以高性能和安全著称,我们在设计和实现过程中也时刻以高性能作为我们的目标,尽可能降低每一处的开销,提升每一处实现的性能。

首先要说明,和 Go 的框架对比性能是极不公平的,因此我们不会着重比较 Volo 和 Kitex 的性能,并且我们给出的数据仅能作为参考,希望大家能够客观看待。同时,由于在开源社区并没有找到另一款成熟的 Rust 语言的 Async 版本 Thrift RPC 框架,而且性能对比总是容易引战,因此我们希望尽可能弱化性能数据的对比,仅会公布我们自己极限 QPS 的数据。

在和 Kitex 相同的测试条件(限制 4C)下,Volo 极限 QPS 为 35W。同时,我们内部正在验证基于 Monoio(CloudWeGo 开源的 Rust Async Runtime)的版本,极限 QPS 可以达到 44W。

从我们线上业务的火焰图来看,得益于 Rust 的静态分发和优秀的编译优化,框架部分的开销基本可以忽略不计(不包含 syscall 开销)。

基于 GAT 设计

我们热爱并追随最新的技术,Volo 的核心抽象使用了 Rust 最新的 GAT 特性,在这个过程中我们也借鉴了 Tower 的设计。Tower 是一个非常优秀的抽象层设计,适用于非 GAT 的情况下。在此我们非常感谢 Tower 团队。

Towerhttps://github.com/tower-rs/tower

通过 GAT,我们可以避免很多不必要的 Box 内存分配,以及提升易用性,给用户提供更友好的编程接口和更符合人体工程学的编程范式。

我们的核心抽象如下:

由于使用了 Rust 的 GAT 特性,因此我们可以解决返回异步 Future 带来的生命周期问题。同时,如果配合 type_alias_impl_trait 使用,效果更佳,比如实现 Timeout 可以使用如下方式:

易用性好

Rust 以难学难用而闻名,我们希望尽可能降低用户使用 Volo 框架以及使用 Rust 语言编写微服务的难度,提供最符合人体工程学和直觉的编码体验。因此,我们把易用性作为我们重要的目标之一。

比如,我们提供了 Volo 命令行工具,用于初始化项目以及管理 IDL。同时,我们将 Thrift 及 gRPC 拆分为两个独立(但共用一些组件)的框架,以提供最符合不同协议语义的编程范式及接口。

我们还提供了 #[service] 宏(可以理解为不需要 Box 的 async_trait)来使得用户可以无心理负担地使用异步来编写 Service 中间件。

通过这个宏,我们编写 Service 中间件可以简化到如下图:

扩展性强

受益于 Rust 强大的表达和抽象能力,通过灵活的中间件 Service 抽象,开发者可以以非常统一的形式,对 RPC 元信息、请求和响应做处理。

比如,服务发现、负载均衡等服务治理功能,都可以以 Service 形式进行实现,而不需要独立实现 Trait。

相关的扩展,我们会放在 github.com/volo-rs 组织下,也欢迎大家贡献自己的扩展到 volo-rs

03 生态系统

Volo 是 RPC 框架的名字,随着 Volo 一起开源的有以下几个项目:

1. Volo-rs:Volo 的相关生态。

2. Pilota:Volo 使用的 Thrift 与 Protobuf 编译器及编解码的纯 Rust 实现(不依赖 protoc)。

3. Motore:Volo 参考 Tower 设计的、使用了 GAT 和 TAIT 的 middleware 抽象层。

4. Metainfo:Volo 用于进行元信息透传的组件,期望定义一套元信息透传的标准。

04 选型建议

“什么情况下应该用 Rust、什么情况下应该用 Go?”这是一个非常经典的问题。在 Volo 团队看来,Rust 和 Go 并不是对立关系,而是合作关系,取长补短。

对于性能不敏感的应用、重 IO 的应用以及需要快速开发快速迭代胜过稳定性的应用,推荐使用 Go,这种应用使用 Rust 并不会带来明显的收益。

对于需要极致性能重计算的应用,以及需要稳定性并能接受一定开发速度损失的应用,推荐使用 Rust,Rust 在极致性能优化和安全性上的优势可以在这类应用中得以发挥。

当然,还有一个很重要的考虑因素,是团队现有的技术栈,即技术储备和人才储备。

05 总结

希望本文能让大家对于 Volo 及相关生态有一个基本的了解。同时,Volo 还处于早期阶段,欢迎各位感兴趣的同学一起加入,共同建设 CloudWeGo 及 Rust 开源社区,向 Volo 提交 Issue 和 PR 共建 Volo。我们诚心期待更多的开发者加入,也期待 Volo 助力越来越多的企业快速构建云原生架构。如果企业客户想内部试用,我们可以排期提供专项技术支持和交流。

参考资料

Volo 概览:https://github.com/cloudwego/volo

Volo Tutorial:https://www.cloudwego.io/zh/docs/volo/

Volo 文档:https://docs.rs/volo

Volo-rs 组织:https://github.com/volo-rs

项目地址

GitHub:https://github.com/cloudwego

官网:www.cloudwego.io

Apache Dubbo 多语言体系再添新员:首个 Rust 语言版本正式发布

作者 | Apache Dubbo技术团队 责编 | 张红月 出品 | 官方投稿

近日,Apache Dubbo 发布了其 Rust 语言实现的首个版本,进一步丰富其多语言体系,这是社区全面对齐 Dubbo3 架构的第三个语言实现。对 Rust 语言社区来说,Apache Dubbo 的加入也是其开源微服务开发框架生态非常重要的补充,Dubbo 也成为 Apache 社区中为数不多的提供 Rust 语言官方支持的项目。

Dubbo Rust 定位为 Dubbo 多语言体系的重要实现,提供高性能、易用、可扩展的 RPC 框架,同时通过接入 Dubbo Mesh 体系提供丰富的服务治理能力。本文主要为大家介绍 Dubbo Rust 项目基本情况,通过一个示例快速体验 Rust 首个正式版本特性,并给出了 Dubbo Rust 社区的近期规划,适合于关注或正在采用 Rust 语言的开发者与企业用户阅读。

云原生时代的 Dubbo

自从 Apache Dubbo 在 2008 年由阿里巴巴开源已来,Dubbo 一直是国内微服务领域最具影响力的开源项目之一,被无数互联网、科技、制造企业选型作为内部微服务体系的基石,根据《中国开源发展研究分析 2022》Apache Dubbo在所有开源项目总排行榜中位列第 6。

Apache Dubbo 是一款支持多语言的、易用的微服务开发框架, 提供一些列组件为构建微服务提供高性能 RPC 通信、流量治理、动态配置、可观测、认证鉴权等服务治理能力。

  • 高性能的基于 HTTP/2 的通用 RPC 协议及 Streaming 通信模型

  • 强大的流量治理能力,如地址发现、负载均衡、路由选址、动态配置等

  • 多语言 SDK 实现,涵盖 Java、Golang、Rust、Node.js 等,更多语言实现将会陆续发布

  • 丰富的生态及组件适配,如服务发现、链路追踪、事务、可观测性等业界主流产品均由官方支持接入

  • 云原生友好,全面兼容 Kubernetes 部署及 Service Mesh 架构,支持接入 Istio、Envoy、Proxyless 等。

除以上核心功能外,Dubbo 还具备以下优势:

  • 开箱即用:1)易用性高,如 Java 版本的面向接口代理特性能实现本地透明调用、2)功能丰富,基于原生库或轻量扩展即可实现绝大多数的微服务治理能力;

  • 面向超大规模微服务集群设计:1)极致性能,业界领先的高性能的 RPC 通信协议设计与实现、2)横向可扩展,轻松支持百万规模集群实例的地址发现与流量治理;

  • 高度可扩展:1)调用过程中对流量及协议的拦截扩展,如 Filter、Router、Load Banlancing 等、2)微服务治理组件扩展,如 Registry、Config Center、Metadata Center 等;

  • 企业级微服务治理能力:1)国内公有云厂商支持的事实标准服务框架、2)多年大型企业规模化实践验证。

在过去的一段时间里,Dubbo 社区一直在积极的拥抱云原生,包括在 Dubbo3(HTTP/2、Service Discovery 等)、Kubernetes、Proxyless Mesh 等方面做了大量的开发与建设工作,而这也取得了很好的回报,我们实现了 Dubbo3 取代全面 HSF 并在阿里巴巴的全面推广落地,同时也得到了大量社区头部企业的跟进。

在接下来,Dubbo 社区在持续跟进以上特性的同时,会将相当一部分精力放在面向用户侧的易用性、稳定性等体验提升上来,这包括官方网站、文档、快速入门、示例实践等的建设,同时,Dubbo 的多语言建设也将是非常重要的一环,因为我们认为让用户知道如何用好 Dubbo 将是社区的一项非常重要的职责。

Dubbo 多语言及 Rust 项目简介

多语言体系建设是 Dubbo3 规划中的重要一环,长期以来,Dubbo2 提供的语言实现仅有 Java、Golang 两种,Dubbo2 的架构设计等都与 Java 语言有较强的绑定关系,如服务定义方式、通信协议、服务发现模型等。为了实现云原生时代微服务多语言,彻底摆脱特定语言绑定的问题,Dubbo 社区陆续启动了 Golang、Rust、Node.js、Python 等语言实现开发工作

  • Dubbo 官网:https://dubbo.apache.org/

  • Dubbo Java:https://github.com/apache/dubbo/

  • Dubbo Golang:https://github.com/apache/dubbo-go/

  • Dubbo Rust:https://github.com/apache/dubbo-rust/

  • Dubbo Node:https://github.com/apache/dubbo-js/

Dubbo Rust 项目的目标是对齐 Dubbo3 的所有核心功能设计,包括基于 HTTP/2 的高性能通信、用户友好的微服务开发编程模式、通过接入 Dubbo Mesh 提供丰富的服务治理能力等,相比于其他语言实现,Dubbo Rust 将很好的利用 Rust 语言带来的极致性能、内存安全和零成本抽象的特点。

对于微服务框架,主流的编程语言都有对应的实现,而 Dubbo Rust 将很好的填补 Rust 领域的空白:

  • Golang:在微服务框架领域已经占据着很重要的地位;开源社区出现了dubbo-go、gRPC、go-micro、go-zero等多个微服务框架

  • Java:国内用户量最大的编程语言,Spring Cloud、Dubbo 等优秀的微服务框架已经非常流行

  • C/C++:brpc、grpc 等微服务框架

  • Rust:目前没有很完善的微服务框架

依托 Dubbo 庞大的用户群,以及 Dubbo 体系下的 Mesh 服务治理整体方案规划。Dubbo Rust 可以轻松地融入到现有的云原生研发体系中,不会增加使用者的研发负担。下图是社区推出的 Dubbo Mesh 架构设计。


在上述架构下,整体分为控制面和数据面两个部分,其中,

  • 控制面负责管理流量治理、地址发现、安全认证、可观测性等服务治理相关的配置信管控工作,包括与K8S等底层技术设施的对接;

  • Dubbo Rust 作为数据面组件,负责接收来自控制面的配置;将配置应用到服务中;同时为服务提供基础的RPC通信能力。

在架构设计方面,Dubbo Rust 将围绕 Dubbo 核心设计以及 Rust 语言的特性进行设计,并将 Dubbo 框架的核心设计输出为文档,从而提升Dubbo框架的易用性。因此,Dubbo Rust 具有如下特点:易用性、高性能以及可扩展,同时面向云原生提供丰富的服务治理能力。

首个 Rust 版本核心能力

Dubbo Rust 首个正式版本为 v0.2.0,v0.2.0 提供的能力包括:

  • 基于 HTTP/2 的 Triple 协议的基础通信能力

  • 基于 IDL 的 RPC 定义支持,Protobuf 来生成代码,同时支持 Serde 序列化

  • request-response、request streaming、response streaming、bi-streaming 通信模型支持

  • 设计了简洁的、可扩展的架构,支持对 Listener、Connector、Filter、Protocol 以及 Invoker 组件进行扩展

Dubbo Rust v0.2.0 的核心组件及通信流程如下图所示:

核心架构已经基本完成,接下来的版本将重点关注核心组件扩展以及服务治理相关组件的设计实现。

Dubbo Rust 开发初体验

完整示例可查看 【Dubbo官网】 -> 【Rust SDK 文档】 https://dubbo.apache.org/zh/docs3-v2/rust-sdk/quick-start/

使用 Dubbo Rust 服务开发的基本步骤为

  1. 环境准备

  2. 使用 IDL 定义服务

  3. 添加 Dubbo Rust 依赖到项目

  4. 编译 IDL

  5. 基于 IDL 编译生成的 stub 编写 Server & Client 逻辑

  6. 运行项目

1. 环境准备

1)安装 Rust 开发环境


curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  1. 安装 protoc 工具

$ brew install protobuf
$ protoc --version  # Ensure compiler version is 3+

注:上述命令为 MacOS 环境下的,其他环境的安装方案请参考官方文档示例。

2. 使用 IDL 定义 Dubbo 服务

Greeter 服务定义如下,包含一个 Unary (request-response) 模型的 Dubbo 服务。


// ./proto/greeter.proto
syntax = "proto3";
option java_multiple_files = true;
package org.apache.dubbo.sample.tri;
// The request message containing the user's name.
message GreeterRequest 
  string name = 1;

// The response message containing the greetings
message GreeterReply 
  string message = 1;

service Greeter
  // unary
  rpc greet(GreeterRequest) returns (GreeterReply);


3. 增加 Dubbo Rust 依赖


# ./Cargo.toml
[package]
name = "example-greeter"
version = "0.2.0"
edition = "2021"
[dependencies]
dubbo = "0.2.0"
dubbo-config = "0.2.0"
[build-dependencies]
dubbo-build = "0.2.0"

4. 编译 IDL

在项目根目录创建 (注意不是 src 目录),创建 build.rs文件并添加以下内容:

// ./build.rs
fn main() 
    dubbo_build::prost::configure()
        .compile(&["proto/greeter.proto"], &["proto/"])
        .unwrap();

这样配置之后,编译项目就可以生成 Dubbo Rust 的 Stub 代码,路径一般在./target/debug/build/example-greeter-/out/org.apache.dubbo.sample.tri.rs。

5. 根据生成的 stub 编写逻辑

5.1 编写 Dubbo Server


// ./src/greeter/server.rs
use ...
#[tokio::main]
async fn main() 
    register_server(GreeterServerImpl 
        name: "greeter".to_string(),
    );

    // Dubbo::new().start().await;
    Dubbo::new()
        .with_config(
            let r = RootConfig::new();
            match r.load() 
                Ok(config) => config,
                Err(_err) => panic!("err: :?", _err), // response was droped
            
        )
        .start()
        .await;


#[allow(dead_code)]
#[derive(Default, Clone)]
struct GreeterServerImpl 
    name: String,


#[async_trait]
impl Greeter for GreeterServerImpl 
    async fn greet(
        &self,
        request: Request<GreeterRequest>,
    ) -> Result<Response<GreeterReply>, dubbo::status::Status> 
        println!("GreeterServer::greet :?", request.metadata);

        Ok(Response::new(GreeterReply 
            message: "hello, dubbo-rust".to_string(),
        ))
    

5.2 配置 dubbo.yaml

dubbo.yaml 指示server端的配置,包括暴露的服务列表、协议配置、监听配置等。


# ./dubbo.yaml
name: dubbo
service:
  org.apache.dubbo.sample.tri.Greeter:
    version: 1.0.0
    group: test
    protocol: triple
    registry: ''
    serializer: json
    protocol_configs:
      triple:
        ip: 0.0.0.0
        port: '8888'
        name: triple
protocols:
  triple:
    ip: 0.0.0.0
    port: '8888'
    name: triple

5.3 编写 Dubbo Client


// ./src/greeter/client.rs
use ...

#[tokio::main]
async fn main() 
    let mut cli = GreeterClient::new().with_uri("http://127.0.0.1:8888".to_string());

    println!("# unary call");
    let resp = cli
        .greet(Request::new(GreeterRequest 
            name: "message from client".to_string(),
        ))
        .await;
    let resp = match resp 
        Ok(resp) => resp,
        Err(err) => return println!(":?", err),
    ;
    let (_parts, body) = resp.into_parts();
    println!("Response: :?", body);

6. 运行项目

6.1 编译

执行 cargo build来编译 server 和 client。

6.2 运行server

执行 ./target/debug/greeter-server 来运行 server,如上文 dubbo.yaml 所配置,server 会监听 8888 端口,并以 triple 协议提供 RPC 服务。


$ ./target/debug/greeter-server
2022-11-06T14:53:33.201033Z  INFO dubbo::framework: url: Some(Url  uri: "triple://0.0.0.0:8888/org.apache.dubbo.sample.tri.Greeter", protocol: "triple", location: "0.0.0.0:8888", ip: "0.0.0.0", port: "8888", service_key: ["org.apache.dubbo.sample.tri.Greeter"], params:  )

6.3 运行client

执行 ./target/debug/greeter-client 来运行 client ,调用triple://127.0.0.1:8888/org.apache.dubbo.sample.tri.Greeter 下的各种方法。

$ ./target/debug/greeter-client
# unary call
Response: GreeterReply  message: "hello, dubbo-rust" 

这样,一个简单的 Dubbo Rust 示例就开发完成了。

Roadmap 及未来规划

Dubbo Rust 致力于成为 Rust 语言社区最受欢迎的微服务开发框架之一,将 Dubbo 在微服务框架领域的积累带给开发者,填补 Rust 社区微服务开发框架的空缺。为了达成这个目标,Dubbo Rust Roadmap 规划总体上分为三个阶段:

首先,提供作为 RPC 框架的基础能力,此阶段重点完成的包括基于 HTTP/2 的 RPC 通信、基于 IDL 的 RPC 定义、其他必要的 RPC 内核组件等

其次是完善 Dubbo Rust 作为微服务框架的高级功能,此阶段包括微服务定义、配置、功能设计等,如服务超时、异步调用、上下文传递、开发者工效学提升(developer ergonomics)、FFI支持等,具体可参见 Dubbo Java 的高级特性。

第三阶段重点是引入丰富的服务治理能力支持,如流量治理、限流降级、可观测性等,这一目标将主要通过融入 Dubbo Mesh 体系,即适配 Dubbo Mesh 控制面实现。

其中,第一阶段的工作已经基本完成,大家可通过上文的 Quick Start 进行深入体验,第二、第三阶段的工作已经在社区全面开展,欢迎感兴趣的社区开发者参与进来。

下图是侧重从第一阶段(RPC框架)、第二阶段(微服务开发框架)的视角对当前 Dubbo Rust 功能完备性的评估和任务拆解。

上图中都是 Dubbo Rust 核心设计的重要组件,保证 Dubbo Rust 具备微服务框架中完整的 RPC 通信能力以及服务治理能力。

Protocol、Filter、Listener、Connector 等组件都是 RPC 通信核心能力

服务注册发现、负载均衡、Cluster、Metadata 为后续服务治理能力做铺垫

除了上图列出的模块以外,还有一些非功能需求也需要支持,例如:

  • Dubbo 多语言框架之间相互通信测试

  • 性能验证与持续的 benchmark 机制

  • 整体架构的持续优化,如核心配置简化以及相应的文档完善

和 Rust 语言一经发布就受到了开发者的热捧一样,Dubbo Rust 当前也是一个非常有活力、非常前沿的社区;另一方面,依赖 Apache Dubbo 社区背后庞大的开发者群体和企业用户,Dubbo Rust 有着非常深厚的用户基础和发展潜力。Dubbo Rust 的快速发展期待社区贡献者的加入。

参与 Dubbo Rust 社区可以收获

  • 见证 Rust 语言社区微服务开源项目的发展

  • 在大型项目中实际使用 Rust 语言,加深对 Rust 语言的理解

  • 获得提名为 Apache Dubbo Committer、PMC 的机会

与 Dubbo 社区及知名企业技术专家面对面的交流机会

欢迎通过以下方式参与 Dubbo Rust 社区:

  • 搜索并关注 Apache Dubbo 微信公众号了解社区最新动态

  • 直接到 GitHub 提交 Issue 或贡献代码 https://github.com/apache/dubbo-rust

以上是关于国内首个基于 Rust 语言的 RPC 框架 — Volo 正式开源!的主要内容,如果未能解决你的问题,请参考以下文章

Apache Dubbo 多语言体系再添新员:首个 Rust 语言版本正式发布

国内首个完整的 Swift 服务端开源项目及详解 - 基于 Vapor 3 框架

清华大学开源首个国内高校自研深度学习框架Jittor

使用 Rust 构建 gRPC 服务器

漫谈微服务RPC架构

6种微服务RPC框架,你知道几个?