楼层: 首页/ 软件技术/ Rust 后端技术栈/ 微服务与分布式:reqwest 与 gRPC
05

微服务与分布式:reqwest 与 gRPC

reqwest, tonic, Resilience

单体写够了,就要拆微服务。服务之间怎么通信?HTTP 用 reqwest(Rust 版 requests),gRPC 用 tonic。这一章讲清楚两种 RPC 的姿势,再加限流熔断这些生产必备的韧性组件。

reqwest:异步 HTTP 客户端

let client = reqwest::Client::builder() .timeout(Duration::from_secs(5)) .build()?; // GET JSON let resp = client.get("https://api.example.com/users") .bearer_auth("token") .send().await? .json::<Vec<User>>().await?; // POST JSON let resp = client.post("https://api.example.com/orders") .json(&NewOrder { item: "book".into() }) .send().await?;

gRPC:tonic 框架

tonic 是 Rust 的 gRPC 框架,配合 prost(protobuf 代码生成)。你写一个 .proto 文件,tonic-build 在编译期生成 Rust trait,你只要实现这个 trait。

// proto/order.proto syntax = "proto3"; package order; service OrderService { rpc GetOrder (GetOrderRequest) returns (Order); } message GetOrderRequest { int64 id = 1; } message Order { int64 id = 1; string item = 2; }
// build.rs —— 编译期生成代码 fn main() -> Result<(), Box<dyn std::error::Error>> { tonic_build::configure().compile_protos(&["proto/order.proto"], &["proto"])?; Ok(()) } // src/main.rs —— 实现 trait pub mod order { tonic::include_proto!("order"); } use order::{order_service_server::{OrderService, OrderServiceServer}, *}; struct MyOrderService; #[tonic::async_trait] impl OrderService for MyOrderService { async fn get_order( &self, req: tonic::Request<GetOrderRequest>, ) -> Result<tonic::Response<Order>, tonic::Status> { Ok(tonic::Response::new(Order { id: req.into_inner().id, item: "book".into(), })) } } #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { tonic::transport::Server::builder() .add_service(OrderServiceServer::new(MyOrderService)) .serve(([0,0,0,0], 50051).into()) .await?; Ok(()) }

韧性组件:限流、熔断、消息队列

能力crate说明
限流governor令牌桶算法,Rust 限流首选
并发限制tower::limit::ConcurrencyLimitAxum 中间件,限制同时在飞请求数
RabbitMQlapin异步 AMQP 客户端
Kafkardkafkalibrdkafka 绑定,生产级
分布式追踪tracing-opentelemetry对接 Jaeger / OTLP

健康检查与分布式追踪

生产微服务的标配:健康检查 endpoint 给负载均衡探活,分布式追踪给运维看请求链路。Rust 里这两件事都很便宜。

// 健康检查:/healthz 给 K8s/LB 探活 async fn healthz() -> &static str { "ok" } // readiness:依赖都活着才返回 200 async fn readyz(State(pool): State<sqlx::PgPool>) -> (axum::http::StatusCode, &static str) { if sqlx::query("SELECT 1").execute(&pool).await.is_ok() { (axum::http::StatusCode::OK, "ready") } else { (axum::http::StatusCode::SERVICE_UNAVAILABLE, "not ready") } }

分布式追踪用 tracing-opentelemetry:Axum 的 TraceLayer 会自动把 W3C traceparent 头透传下去,tonic 拦截器把 span context 塞进 gRPC metadata。一个请求跨服务的完整路径在 Jaeger 里一目了然。

记
本章小结

① HTTP 调用用 reqwest,gRPC 用 tonic + prost,proto 先行。

② 生产韧性:governor 限流、tower 并发限制、lapin/rdkafka 消息队列、tracing-opentelemetry 追踪。

③ 健康检查分 /healthz(进程活着就行)和 /readyz(依赖都活着),给 K8s/LB 用。