gRPC для Rust: библиотеки и примеры
gRPC — это высокопроизводительный фреймворк для удалённого вызова процедур (RPC), разработанный Google. Он использует Protocol Buffers (protobuf) для сериализации данных и HTTP/2 для транспорта. В экосистеме Rust основными библиотеками для работы с gRPC являются tonic и grpc-rs. В этой статье мы подробно рассмотрим обе библиотеки, их возможности и приведём практические примеры кода.
Почему gRPC в Rust?
Rust — язык системного программирования с акцентом на безопасность памяти и производительность. gRPC на Rust позволяет создавать:
- Высоконагруженные микросервисы
- Потоковые сервисы реального времени
- Кроссплатформенные клиент-серверные приложения
- Интеграцию с существующей gRPC-инфраструктурой
Основные библиотеки
1. Tonic — современный и рекомендуемый выбор
Tonic — это асинхронная библиотека gRPC, построенная на основе tokio и hyper. Она активно поддерживается сообществом и считается стандартом для gRPC в Rust.
Преимущества tonic:
- Полная поддержка gRPC (унарные, серверные, клиентские и двунаправленные потоки)
- Генерация кода через
tonic-buildна основе.protoфайлов - Интеграция с
tokio(асинхронный рантайм) - Поддержка TLS, балансировки нагрузки и интерсепторов
- Активное сообщество и хорошая документация
2. grpc-rs — альтернатива от PingCAP
grpc-rs — это Rust-обёртка над C-библиотекой gRPC Core. Используется в проекте TiKV. Подходит для случаев, когда требуется максимальная совместимость с оригинальным gRPC C-стебом.
Особенности grpc-rs:
- Обёртка над gRPC Core (C-библиотека)
- Поддержка всех типов gRPC-вызовов
- Меньше «магии» — больше контроля
- Требует установки
protocиcmake - Меньше популярность по сравнению с tonic
Рекомендация: Для большинства новых проектов выбирайте tonic. grpc-rs стоит использовать, если вам нужна интеграция с существующим C-кодом gRPC.
Настройка проекта с tonic
Создайте новый проект:
cargo new grpc-example
cd grpc-example
Добавьте зависимости в Cargo.toml:
[dependencies]
tonic = "0.11"
prost = "0.12"
tokio = { version = "1", features = ["full"] }
[build-dependencies]
tonic-build = "0.11"
Создайте файл proto/hello.proto:
syntax = "proto3";
package hello;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
Настройте сборку — создайте build.rs:
fn main() -> Result<(), Box<dyn std::error::Error>> {
tonic_build::compile_protos("proto/hello.proto")?;
Ok(())
}
Пример сервера на tonic
Создайте src/server.rs:
use tonic::{transport::Server, Request, Response, Status};
use hello::greeter_server::{Greeter, GreeterServer};
use hello::{HelloRequest, HelloReply};
pub mod hello {
tonic::include_proto!("hello");
}
#[derive(Default)]
pub struct MyGreeter;
#[tonic::async_trait]
impl Greeter for MyGreeter {
async fn say_hello(
&self,
request: Request<HelloRequest>,
) -> Result<Response<HelloReply>, Status> {
let name = request.into_inner().name;
let reply = HelloReply {
message: format!("Привет, {}!", name),
};
Ok(Response::new(reply))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = "[::1]:50051".parse()?;
let greeter =