Learn Rust Coding · 课时

从 gRPC 客户端调用

使用该服务。

第 4 / 4 课13 个步骤

从 gRPC 客户端调用 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。

生成的客户端

tonic 会为每个服务生成一个客户端结构体,例如 GreeterClient,并将其放在 greeter_client 模块中。它为每个 rpc 提供一个异步方法。

您可以通过传输通道构造它,也可以直接连接到端点。

use greeter::v1::greeter_client::GreeterClient;
use greeter::v1::HelloRequest;

连接到服务器

最简单的方式是使用 GreeterClient::connect,它接收地址字符串并返回已连接的客户端。

它必须在异步上下文中运行,因此请在 #[tokio::main] 下使用 .await 调用它。

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = GreeterClient::connect("http://[::1]:50051").await?;
    Ok(())
}

发起一元调用

将消息包装在 tonic::Request 中(或使用 Request::new),然后调用生成的方法。

响应是一个 tonic::Response;调用 .into_inner() 读取其中的消息。

let request = tonic::Request::new(HelloRequest { name: "Ada".into() });
let response = client.say_hello(request).await?;
println!("{}", response.into_inner().message);

处理 Status 错误

如果服务器返回错误,此调用会得到 Err(Status)。检查 status.code() 和 status.message(),并据此进行处理。

这与服务器端的行为相对应:NotFound 或 Unauthenticated 等状态码会传回客户端。

match client.say_hello(req).await {
    Ok(resp) => println!("{}", resp.into_inner().message),
    Err(status) => eprintln!("{}: {}", status.code(), status.message()),
}

构建通道

如需复用和配置,请使用 Endpoint 显式构建 Channel。您可以设置超时、TCP 保活和连接选项。

然后使用 GreeterClient::new(channel) 构造客户端。

use tonic::transport::{Channel, Endpoint};
let channel = Endpoint::from_static("http://[::1]:50051")
    .timeout(std::time::Duration::from_secs(5))
    .connect()
    .await?;
let mut client = GreeterClient::new(channel);

发送元数据

发送请求前,将身份验证令牌等标头插入请求元数据,即可附加这些标头。

请使用 MetadataValue 表示值;它必须是有效的 ASCII 标头值。

use tonic::metadata::MetadataValue;
let mut req = tonic::Request::new(HelloRequest { name: "Ada".into() });
let token: MetadataValue<_> = "Bearer abc123".parse()?;
req.metadata_mut().insert("authorization", token);

单次调用截止时间

设置截止时间,避免服务器响应缓慢导致客户端一直等待。如果超时,请求上的 set_timeout 会以 DeadlineExceeded 状态中止请求。

截止时间会传递到服务器,服务器可以提前停止工作。

let mut req = tonic::Request::new(HelloRequest { name: "Ada".into() });
req.set_timeout(std::time::Duration::from_secs(2));
let resp = client.say_hello(req).await?;

接收服务器流

服务器流式调用会返回一个流。使用 into_inner() 获取它,然后在循环中通过 message().await 拉取消息,直到得到 None。

每次迭代都会得到一条解码后的响应。

let mut stream = client.server_stream(req).await?.into_inner();
while let Some(item) = stream.message().await? {
    println!("{:?}", item);
}

客户端流式传输

对于客户端流式调用,请传入请求的异步流。使用 tokio_stream 包装迭代器或通道,然后将其交给该方法。

完成发送后,服务器才会返回唯一的响应。

use tokio_stream::iter;
let outbound = iter(vec![msg1, msg2, msg3]);
let response = client.client_stream(Request::new(outbound)).await?;
println!("{:?}", response.into_inner());

TLS 连接

如需加密传输,请使用 CA 证书和服务器域名配置 ClientTlsConfig,然后通过 https 连接。

这要求 tonic 依赖启用 tls 功能。

use tonic::transport::{ClientTlsConfig, Endpoint};
let tls = ClientTlsConfig::new().domain_name("example.com");
let channel = Endpoint::from_static("https://example.com:50051")
    .tls_config(tls)?
    .connect()
    .await?;

复用客户端

底层 Channel 易于克隆,并会通过一个 HTTP/2 连接复用请求。请在多个任务之间克隆客户端,而不要反复重新连接。

这样可以在并发场景下降低连接建立成本。

let client = GreeterClient::new(channel);
let mut c1 = client.clone();
let mut c2 = client.clone();
// use c1 and c2 in separate tokio tasks

快速检查

在 tonic 中,如何读取一元客户端调用的结果?

回顾

您连接了生成的客户端,发起了一元调用,处理了 Status 错误,构建了经过配置的通道,发送了元数据,设置了截止时间,接收了服务器流和客户端流,启用了 TLS,并复用了易于克隆的客户端。

现在,您已经可以端到端地构建完整的基于 tonic 的 gRPC 服务。

免费开始

用 AI 导师学习 Rust — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
39
课程
144

常见问题解答

「从 gRPC 客户端调用」课时是免费的吗?

是的 — 「从 gRPC 客户端调用」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。

「从 gRPC 客户端调用」这节课中我会学到什么?

使用该服务。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Learn Rust Coding 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「从 gRPC 客户端调用」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Learn Rust Coding 课中编写并运行代码吗?

能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. Protobuf 与服务定义
  2. 使用 tonic-build 生成代码
  3. 实现 gRPC 服务器
  4. 从 gRPC 客户端调用
← 返回 Learn Rust Coding