入门指南:基于 async/await 的高性能 gRPC 客户端与服务端实现)
后端RPC框架【免费下载链接】grpc-rustA native gRPC client server implementation with async/await support.项目地址https://gitcode.com/GitHub_Trending/to/grpc-rust点击查看免费下载本指南以仓库根目录 README.md 为骨架融合 helloworld 教程、routeguide 教程 以及tonic源码细节系统讲解如何在 Rust 中基于异步生态搭建 gRPC 服务端与客户端。读完本文你将掌握 gRPC 四类 RPC 的定义与编码、tonic的三大核心组件架构、特性开关与 TLS/压缩/负载均衡等生产级能力并能独立从零写出一个可运行、可验证的 HelloWorld 示例。项目概览gRPC 的 Rust 原生实现README.md 明确指出本仓库是 gRPC 的一个 Rust 实现。gRPC 是一个高性能、开源、通用的 RPC 框架其设计把移动端和 HTTP/2 放在首位。仓库中的核心 cratetonic是基于 HTTP/2 的 gRPC 实现聚焦三个关键词高性能high performance、互操作性interoperability与灵活性flexibility。它被设计出来的目的有两层对async/await提供一等公民first class支持作为用 Rust 编写生产系统时的核心构建块core building block。需要留意的是README 中有一则重要提示——tonic的master分支当前正在准备破坏性变更breaking changes若想使用最新已发布版本应关注0.14.x分支。仓库内tonic/Cargo.toml显示的版本为0.14.6工作区级的rust-version 1.88即 MSRV最低支持的 Rust 版本与 README 中 “tonics MSRV is1.88” 的声明一致。三大核心组件README 的 Overview 一节把tonic拆解为三个相互协作的组成部分组件职责底层技术通用 gRPC 实现提供与具体 HTTP/2 栈、编码格式解耦的通用 gRPC 语义通过一组泛型 trait 支撑任意 HTTP/2 实现与任意编码tonic 自身高性能 HTTP/2 实现提供开箱即用的 Channel客户端与 Server服务端hyper、基于稳健的tokio栈构建代码生成codegen从protobuf定义构建客户端与服务端代码prost也就是说tonic在最低层面允许使用任意 HTTP/2 实现配合不同类型的 gRPC 编码格式而默认提供的transport模块则是一套基于tokio、hyper、tower的“全家桶”实现同时被设计成一份参考实现供需要更丰富特性的团队在此基础上继续扩展。功能特性清单README 列出了tonic的核心特性这些特性也都能在 examples 中找到对应的完整示例代码双向流式传输Bi-directional streaming—— 客户端与服务端可同时收发消息流对应 streaming 示例 与 routeguide 教程中的RouteChat高性能异步 IOHigh performance async io—— 基于tokiohyper的异步网络栈互操作性Interoperability—— 遵循标准 gRPC 协议可与各语言 gRPC 实现互通interop 目录提供了互操作测试实现TLS 支持由rustls背书—— 通过特性开关启用示例见 tls 示例、tls_client_auth 示例 与 tls_rustls 示例负载均衡Load balancing—— 客户端侧可配置多种均衡策略见 load_balance 示例 与 dynamic_load_balance 示例自定义元数据Custom metadata—— 通过tonic::metadata模块metadata/key.rs、metadata/map.rs在请求/响应中附加键值元数据认证Authentication—— 服务端与客户端拦截器实现见 authentication 示例健康检查Health Checking—— 提供标准 gRPC 健康检查服务的实现见 tonic-health crate 与 health 示例。此外tonic/src/lib.rs 的 crate 级文档确认该库的定位是“用于生产系统的核心构建块”强调性能、互操作性与灵活性三者的平衡。特性开关Feature Flags按需裁剪依赖tonic通过 Cargo feature 精细控制启用哪些能力。tonic/src/lib.rs 与 tonic/Cargo.toml 给出了完整清单按“默认开启 / 默认关闭”整理如下默认开启default [router, transport, codegen]特性作用transport启用基于hyper、tower、tokio的“全家桶”客户端与服务端实现同时开启server与channelserver仅启用transport中服务端部分依赖h2、hyper?/server、socket2、tower?/limit、tower?/load-shed等channel仅启用transport中客户端 Channel 部分依赖h2、hyper?/client、hyper-timeout、tower?/balance等router启用基于axum的服务路由codegen启用tonic-build所需的导出与可选依赖async-trait默认关闭按需开启特性作用tls-ring基于rustls的 TLS 选项使用ringlibcrypto providertls-aws-lc基于rustls的 TLS 选项使用aws-lc-rslibcrypto provider与tls-ring二选一tls-native-roots通过rustls-native-certs为 gRPC 客户端注入系统信任根证书tls-webpki-roots通过webpki-roots为 gRPC 客户端注入标准信任根证书tls-connect-info为常见 TLS connector 增加Connected实现便于在不启用其他tls-*特性时配合connect_with_connector使用自定义 TLS connectorgzip启用请求、响应与流的 gzip 压缩依赖flate2deflate启用 deflate 压缩依赖flate2zstd启用 zstd 压缩依赖zstd从 tonic/Cargo.toml 的源码可以看到tls-ring与tls-aws-lc都经由内部特性_tls-any统一接通tokio运行时与tls-connect-info二者本质是tokio-rustls下两种 libcrypto 提供者的选择。消息大小上限防止内存耗尽tonic/src/lib.rs 还披露了一个容易被忽视的默认配置服务端与客户端都可设置最大编码/解码消息大小以确保入站 gRPC 消息不会耗尽系统内存。默认解码上限为 4MB编码上限为usize::MAX。生产环境中建议按业务需要显式调整。依赖说明关于 protocREADME 的 Dependencies 一节提醒了一个实际工程中常见的坑tonic-build的某些 API例如tonic_build::compile_protos()需要protocProtocol Buffers 编译器来编译.proto资源文件。这意味着构建机器上需要安装 Protocol Buffers 编译器可参考 Protocol Buffers 官方下载页获取对应平台的protoc。与之对应tonic-prost-buildtonic-prostcrate 的构建端见 tonic-prost提供了基于prost的纯 Rust 编译路径这也是本仓库教程默认采用的方式。快速上手从 HelloWorld 开始README 推荐的入门路径是 helloworld 教程适合首次使用tonic的读者进阶路径是 routeguide 教程覆盖tonic全部特性。下面按教程脉络从零搭建一个可运行的 gRPC 服务端与客户端。第一步创建项目并定义 proto$ cargo new helloworld-tonic $ cd helloworld-tonic $ mkdir proto $ touch proto/helloworld.prototonic对.proto文件存放位置没有硬性要求教程中放在项目根目录的proto/下即可。定义服务时先在proto文件中声明syntax与package名——这个 package 名就是后续include_proto!宏查找生成代码的依据syntax proto3; package helloworld; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply); } message HelloRequest { string name 1; } message HelloReply { string message 1; }gRPC 共支持四类服务方法简单 RPC、服务端流式、客户端流式、双向流式tonic全部支持HelloWorld 教程只用到最简单的简单 RPC四类方法都会用到的话请看 routeguide 教程仓库中的完整定义见 examples/proto/routeguide/route_guide.proto。第二步配置 Cargo.toml 与 build.rsexamples/helloworld-tutorial.md 给出了完整依赖清单。核心要点[[bin]] # Bin to run the HelloWorld gRPC server name helloworld-server path src/server.rs [[bin]] # Bin to run the HelloWorld gRPC client name helloworld-client path src/client.rs [dependencies] tonic * prost 0.14 tonic-prost * tokio { version 1.0, features [macros, rt-multi-thread] } [build-dependencies] tonic-prost-build *然后在项目根目录不是src下创建build.rs把 proto 编译接入 cargo 构建流程fn main() - Result(), Boxdyn std::error::Error { tonic_prost_build::compile_protos(proto/helloworld.proto)?; Ok(()) }routeguide 教程中用的是带unwrap_or_else的错误处理变体效果等价。这样每次cargo build都会自动保持生成代码与.proto定义同步无需额外步骤。第三步编写服务端服务端实现分两步把生成代码引入作用域然后实现生成的服务 trait。首先生成代码通过include_proto!宏引入参数是 proto 里的package 名不是文件名use tonic::{transport::Server, Request, Response, Status}; use hello_world::greeter_server::{Greeter, GreeterServer}; use hello_world::{HelloReply, HelloRequest}; pub mod hello_world { tonic::include_proto!(helloworld); }接着实现Greetertrait。注意#[tonic::async_trait]属性宏让 trait 支持 async 方法其内部基于async-trait对应tonic的codegen特性#[derive(Debug, Default)] pub struct MyGreeter {} #[tonic::async_trait] impl Greeter for MyGreeter { async fn say_hello( self, request: RequestHelloRequest, ) - ResultResponseHelloReply, Status { println!(Got a request: {:?}, request); let reply HelloReply { message: format!(Hello {}!, request.into_inner().name), }; Ok(Response::new(reply)) } }注意gRPC 请求与响应的字段是私有的必须通过request.into_inner()解包后才能访问name等字段同理构造响应时要Response::new(...)包装。最后在tokio运行时上启动服务#[tokio::main] async fn main() - Result(), Boxdyn std::error::Error { let addr [::1]:50051.parse()?; let greeter MyGreeter::default(); Server::builder() .add_service(GreeterServer::new(greeter)) .serve(addr) .await?; Ok(()) }运行cargo run --bin helloworld-server即可启动服务。验证方式有两种使用支持 gRPC 的 GUI 客户端如 Postman或使用grpcurl$ grpcurl -plaintext -import-path ./proto -proto helloworld.proto -d {name: Tonic} [::1]:50051 helloworld.Greeter/SayHello预期响应{ message: Hello Tonic! }第四步编写客户端客户端同样通过include_proto!引入生成代码然后connect到服务端地址发起调用。GreeterClient::connect返回的客户端是mut 的因为它需要维护内部状态use hello_world::greeter_client::GreeterClient; use hello_world::HelloRequest; pub mod hello_world { tonic::include_proto!(helloworld); } #[tokio::main] async fn main() - Result(), Boxdyn std::error::Error { let mut client GreeterClient::connect(http://[::1]:50051).await?; let request tonic::Request::new(HelloRequest { name: Tonic.into(), }); let response client.say_hello(request).await?; println!(RESPONSE{:?}, response); Ok(()) }分别在两个终端运行cargo run --bin helloworld-server与cargo run --bin helloworld-client服务端终端会打印出收到的请求客户端终端会打印出响应——一个最小可运行的 gRPC 闭环就完成了。深入四类 RPC 与流式处理模式routeguide 教程 用一个“路线导航”应用完整演示了 gRPC 的四类服务方法其定义方式如下// 简单 RPC客户端发一个请求等一个响应 rpc GetFeature(Point) returns (Feature) {} // 服务端流式stream 放在响应类型前 rpc ListFeatures(Rectangle) returns (stream Feature) {} // 客户端流式stream 放在请求类型前 rpc RecordRoute(stream Point) returns (RouteSummary) {} // 双向流式请求与响应前都放 stream rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}在实现层面四类方法对应的tonic::RequestT/ 返回值形态完全不同examples/src/routeguide/server.rs 提供了完整参考实现简单 RPCget_feature接收RequestPoint返回ResultResponseFeature, Status本质是一次普通函数调用服务端流式list_features需要返回一个流。典型做法是用tokio::sync::mpsc::channel开异步任务生产数据再把ReceiverStream包进tonic::Response返回type ListFeaturesStream ReceiverStreamResultFeature, Status; async fn list_features( self, request: RequestRectangle, ) - ResultResponseSelf::ListFeaturesStream, Status { let (tx, rx) mpsc::channel(4); let features self.features.clone(); tokio::spawn(async move { for feature in features[..] { if in_range(feature.location.as_ref().unwrap(), request.get_ref()) { tx.send(Ok(feature.clone())).await.unwrap(); } } }); Ok(Response::new(ReceiverStream::new(rx))) }客户端流式record_route方法接收Requesttonic::StreamingPoint用stream.next().await逐个消费输入流同时折叠出统计结果流结束后返回单个RouteSummary双向流式route_chat接收输入流、返回输出流常借助async-stream的try_stream!宏做“流到流”的异步变换type RouteChatStream PinBoxdyn StreamItem ResultRouteNote, Status Send static; async fn route_chat( self, request: Requesttonic::StreamingRouteNote, ) - ResultResponseSelf::RouteChatStream, Status { let mut notes HashMap::new(); let mut stream request.into_inner(); let output async_stream::try_stream! { while let Some(note) stream.next().await { let note note?; let location note.location.unwrap(); let location_notes notes.entry(location).or_insert(vec![]); location_notes.push(note); for note in location_notes { yield note.clone(); } } }; Ok(Response::new(Box::pin(output) as Self::RouteChatStream)) }客户端调用流式方法时返回流的消费方式是stream.message().await?循环读取直到流结束见 examples/src/routeguide/client.rs 中的print_features。客户端侧发送流时可以用tokio_stream::iter(集合)把Vec廉价地转成Stream再包进Request。运行完整示例仓库根目录执行$ cargo run --bin routeguide-server $ cargo run --bin routeguide-client # 另开终端客户端终端会以每秒一行的节奏打印双向流式 RPC 的输出形如NOTE RouteNote { location: Some(Point { latitude: 409146139, longitude: -746188906 }), message: at 1.000319208s }代码生成配置默认配置之外的工作流routeguide 教程 的附录专门讲解了tonic_prost_build的配置。默认的代码生成配置适合自包含示例与小项目但当遇到以下场景时就需要定制在不同 crate里分别构建 Rust 客户端与服务端在更大的多语言项目中只构建 Rust 侧的一部分编辑器无法索引默认位置OUT_DIR下生成的文件想要 IDE 支持。tonic_prost_build可以通过configure()链式方法定制输出例如把.proto定义留在独立 crate、按需而非构建时生成代码并指定输出目录fn main() { tonic_prost_build::configure() .build_client(false) // 只生成服务端代码 .out_dir(another_crate/src/pb) // 输出到指定目录 .compile_protos([path/my_proto.proto], [path]) .expect(failed to compile protos); }另一种工作流是将.proto定义放进独立 crate 后直接以该 crate 作为依赖被其他 crate 引用。README 中 tonic-buildprost系的服务代码生成与 tonic-prost 正是这一职责的承载者。仓库中 codegen/src/main.rs 与examples/generated/下的生成结果如 helloworld/helloworld_grpc.pb.rs可以让你直观了解生成代码的结构。项目布局一个完整 gRPC 生态的工作区README 的 Project Layout 一节把仓库划分成若干可独立复用的 crate。结合根 Cargo.toml 的工作区成员各模块定位如下目录定位tonic通用 gRPC 与 HTTP/2 客户端/服务端实现核心 crateversion 0.14.6tonic-build基于prost的服务代码生成tonic-prost面向prost编码的 codec 与集成层tonic-types基于prost的 gRPC 工具类型含 gRPC Well Known Types 支持tonic-health标准 gRPC 健康检查服务实现同时是 unary 与响应流式 RPC 的示范tonic-reflection基于 tonic 的 gRPC reflection 实现examples演示 TLS、负载均衡、双向流式等特性的 gRPC 示例interop互操作测试实现覆盖大量 gRPC 特性场景除此之外仓库还包含面向 xDS 控制面集成的一族 cratexds-client、xds-client-opentelemetry、tonic-xds、grpc-xdsgRPC 生态中的高级负载均衡与服务发现方案以及曾经的grpc、grpc-protobuf、grpc-benchmark等模块。对生产环境有高级路由、重试、熔断、负载均衡需求的读者可深入 tonic-xds 与 xds-client 探索。生产化要点小结综合 README、教程与源码把tonic投入生产前建议关注以下几点版本与 MSRV当前工作区rust-version 1.88见 Cargo.tomltonic0.14.6 要求 Rust 1.88 及以上如需使用最新已发布代码关注0.14.x分支而非正在变更的master。按需开启特性TLStls-ring/tls-aws-lc二选一可叠加tls-native-roots/tls-webpki-roots信任根、压缩gzip/deflate/zstd默认都是关闭的用到才开避免引入多余依赖。消息大小上限默认解码 4MB / 编码usize::MAX超限场景要显式调大解码限制或对响应流做分页。构建依赖若使用tonic_build::compile_protos()这类 API构建机需安装protoc纯 Rust 的tonic-prost-build路径则无此要求。中间件与拦截器tonic内部基于tower与hyper天然支持可组合的中间件栈——认证、限流、负载均衡tower的limit、balance、load-shed均已接入channel/server特性见 tonic/Cargo.toml示例见 interceptor 示例 与 tower 示例。获取帮助与参与贡献README 建议的求助路径依次是先查 API 文档若没有答案可在 Tonic Discord 频道提问仍无法解决再开 issue 提交问题。仓库本身是只读的欢迎按 CONTRIBUTING.md 的指引参与贡献。项目采用 MIT 许可。除非明确声明任何为 Tonic 贡献的代码默认按 MIT 条款授权不附加额外条件。赞分享后端RPC框架【免费下载链接】grpc-rustA native gRPC client server implementation with async/await support.项目地址https://gitcode.com/GitHub_Trending/to/grpc-rust点击查看免费下载相关推荐OXChart自定义图表库入门指南从安装到绘制第一个饼图的完整教程OXChart自定义图表库入门指南从安装到绘制第一个饼图的完整教程 OXChart是一款功能强大的自定义图表库专为Android开发者打造使用简单且支持灵gRPC Ruby 错误与取消处理实战基于 GRPC::BadStatus 的服务端抛出与客户端捕获指南gRPC Ruby 错误与取消处理实战基于 GRPC::BadStatus 的服务端抛出与客户端捕获指南 本篇技术指南聚焦 gRPC 官方仓库中 exampl后端RPC框架微服务通信gRPC Server Reflection 服务端接入指南基于 google.golang.org/grpc/reflection 的注册与实现解析gRPC Server Reflection 服务端接入指南基于 google.golang.org/grpc/reflection 的注册与实现解析 gRP云原生集群管理虚拟化多集群上一篇老游戏在 Windows 10/11 上花屏卡顿DDrawCompat 用一个 dll 就能救回来下一篇Source Sans 3 可变字体实战教程用两个文件替代 14 个静态字体并解锁任意字重的完整方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考