如何在Rust中设置gRPC服务器和客户端

493 阅读4分钟

[

Doğukan Akkaya

](medium.com/@dogukanakk…)

Doğukan Akkaya

关注

6月25日

-

4分钟阅读

[

拯救

](medium.com/m/signin?ac…)

如何在Rust中设置gRPC服务器和客户端

让我们建立一个Rust Todo应用程序

在这个故事中,我们将用Rust创建一个使用gRPC的基本Todo应用程序。首先,我想给你一个关于gRPC协议缓冲区的快速概述。

什么是gRPC?

gRPC是一个现代开源的高性能远程过程调用(RPC)框架,可以在任何环境下运行。

RPC代表远程过程调用,g ,开头代表通用,或者对某些人来说它代表谷歌。但实际上,你可以在这里看到:g_stands_for,gRPC团队在每个版本中都会改变g 的含义 :)

我假设你对常见的REST API很熟悉。他们是通过JSON对象进行通信的,在gRPC中,我们使用协议缓冲器来代替JSON来序列化数据。

协议缓冲区

协议缓冲区是谷歌的语言中立、平台中立、可扩展的机制,用于序列化结构化数据。

在gRPC中,传输的数据(序列化)是以二进制形式存在的。因此,这意味着它比JSON或XML更快,因为它占用的空间更少,而更少的空间带来更小的带宽。

在Rust中使用gRPC

首先,创建一个新的货物包。

cargo new rust-grpc

在创建了货物包之后,我们必须为gRPC添加一些依赖项,并在Cargo.toml ,为我们的服务器和客户端二进制文件创建二进制定义。

  • tonic 是Rust的HTTP/2上的gRPC实现。
  • tonic-build 是用于将我们的proto文件编译成Rust代码。
  • prost 是Rust的协议缓冲区实现。
  • tokio 是Rust的一个异步运行时间,你们中的许多人可能已经知道了。

创建你的proto文件。

proto/todo.proto

这就是Proto文件的语法。让我们来讨论一下proto文件的语法。

  • syntax 定义了proto文件的版本。
  • import 允许你使用其他proto文件的定义。例如,由于我们的 函数没有请求参数,我们要导入 ,像下面这样定义它。GetTodos empty.proto
  • message 将消息视为定义请求和响应的接口。分配给字段的数字代表 。字段编号是Protobuf的一个重要部分。它们用于识别二进制编码数据中的字段,这意味着它们不能在你的服务的各个版本中改变。(field numbers更多信息) 另外,如果你想知道什么是 ,可以把它想象成一个数组。
    repeated
  • service 你也可以把它想象成一个接口,但这次它定义了服务中的函数是什么,它们需要什么,以及它们返回什么。

将Proto文件编译为Rust代码。

build.rs

服务器代码

src/server.rs

让我们快速看看这里发生了什么。

  • 首先,我们要包括来自tonic,Request,Response等的所需结构。
  • 此外,我们还必须包括从proto文件中编译出来的Rust结构。你也可以在你的/target/debug/build 目录中看到它们。
  • 现在我们需要创建我们的TodoService ,并为该服务实现Todo 特质。
    添加todos 属性来存储我们的todo项目。我们添加Mutex 的原因是,我们需要一个对todos的可变引用。由于self 是不可变的(由于Todo trait的定义,我们不能把它当作可变的),我们不能修改todos (推送、删除等),为什么不使用RefCell ?这是因为我们需要线程安全。
    了解更多关于MutexInterior Mutability Pattern
  • 毕竟,我们正在实现我们的函数,get_todos 将简单地返回带有todo项目的GetTodosResponse
    create_todo 函数将获得请求的有效载荷,从TodoItem 结构中创建todo项目,将其推送到self.todos (我们正在克隆todo_item ,否则Rust编译器会因为借用规则use of moved value 而恐慌),并返回带有创建的todo和状态true的CreateTodoResponse
  • 最后,我们启动我们的服务器,在0.0.0.0:50051

客户端代码

src/client.rs

再次,让我们快速看看这里发生了什么。

  • 首先,我们包括我们的TodoClientCreateTodoRequest ,这是从proto文件中编译的。
  • 现在我们再次编写我们的main 函数。我们基本上连接到0.0.0.0:50051 ,并为get_todos 创建一个空的请求(你会记得我们在proto文件中没有为GetTodos 的请求参数。)
    ,然后发送请求,等待响应,最后是println!
    对于create_todo 几乎一样,但这次我们也将CreateTodoRequest 结构传递到请求中,然后再次println!

做完这一切后,构建、运行服务器二进制文件,等待它启动,然后也运行客户端二进制文件。

cargo buildcargo run --bin grpc-servercargo run --bin grpc-client

我希望这对你也有用 :)

如果没有,你可能需要安装protobuf 包,这取决于你的操作系统。我起初也遇到了一些问题,但后来我决定在Docker容器中运行我的服务器。
如果你也想这么做,请看我的GitHub仓库。

一些资源