Вызовы из клиента 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 — локальная установка не требуется.
Все уроки этого курса
- Protobuf и определения сервисов
- Генерация кода с tonic-build
- Реализация сервера gRPC
- Вызовы из клиента gRPC