0Pricing
Learn Rust Coding · Урок

Вызовы из клиента gRPC

Используйте сервис.

«Вызовы из клиента gRPC» — бесплатный урок Learn Rust Coding на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения 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()),
}

Создание канала

Для повторного использования и настройки явно создайте Channel с помощью Endpoint. Вы можете задать время ожидания, поддержку TCP keepalive и параметры соединения.

Затем создайте клиента с помощью 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-соединения

Для зашифрованного транспорта настройте ClientTlsConfig с сертификатом CA и доменом сервера, а затем подключитесь через 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 и повторно использовали недорогие клонированные клиенты.

Теперь Вы можете создавать полноценные службы gRPC на основе tonic от начала до конца.

Часто задаваемые вопросы

Урок «Вызовы из клиента gRPC» бесплатный?

Да — полный текст урока «Вызовы из клиента gRPC» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Learn Rust Coding, подпишись на CoddyKit PRO. Курс Learn Rust Coding содержит 4 уроков всего.

Чему я научусь в уроке «Вызовы из клиента gRPC»?

Используйте сервис. Ты практикуешь Learn Rust Coding с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Learn Rust Coding?

Предыдущий опыт не требуется. Learn Rust Coding на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 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