当前位置: 首页 > article >正文

使用 Tonic 构建高性能异步 gRPC 服务

使用 Tonic 构建高性能异步 gRPC 服务在分布式系统开发中gRPC 作为 Google 开源的高性能 RPC 框架凭借 Protobuf 二进制序列化的高效性和 HTTP/2 传输的优势成为服务间通信的首选方案。而在 Rust 生态中Tonic 框架以其原生异步支持、类型安全、高性能的特性成为实现 gRPC 服务的最优选择之一。本文将从 Tonic 基础入手带你从零搭建 gRPC 服务与客户端。搭建 Tonic 开发环境安装 Protobuf 编译器Tonic 依赖 Protobuf 编译器来解析.proto文件并生成 Rust 代码不同系统的安装方式如下# LinuxUbuntu/Debiansudoapt-getinstallprotobuf-compiler# macOSbrewinstallprotobuf# Windowswingetinstall-e--idGoogle.Protobuf安装完成后执行protoc --version验证是否成功。创建项目并配置依赖接下来创建一个包含服务端和客户端的 Rust 项目模拟真实的服务通信场景cargonew tonic-democdtonic-demo修改Cargo.toml添加核心依赖和构建依赖# 二进制目标服务端和客户端 [[bin]] name server path src/server.rs [[bin]] name client path src/client.rs [dependencies] tokio { version 1, features [full] } # tokio 的流式处理需要用到 tokio-stream { version 0.1, features [full] } tonic 0.14 tonic-prost 0.14 prost 0.14 prost-types 0.14 anyhow 1.0 chrono 0.4 [build-dependencies] tonic-prost-build 0.14 anyhow 1.0创建build.rs文件用于配置 Protobuf 编译规则告诉 Tonic 在构建时自动生成代码useanyhow::Result;fnmain()-Result(){println!(cargo:rerun-if-changedbuild.rs);println!(cargo:rerun-if-changedproto/chat.proto);// 编译 proto 目录下的所有 .proto 文件tonic_prost_build::compile_protos(proto/chat.proto)?;Ok(())}入门案例实现一个双向流式聊天服务gRPC 支持四种服务方法一元 RPC单次请求-响应、服务端流式、客户端流式、双向流式。其中双向流式适合实时聊天、即时数据推送等场景本文将基于 Tonic 实现一个简单的双向流式聊天服务完整覆盖 Protobuf 定义、服务端实现、客户端测试全流程。定义 Protobuf 接口gRPC 是接口定义优先的首先需要通过 Protobuf 定义服务接口和数据结构。在项目根目录创建proto文件夹新建chat.proto文件syntax proto3; package chat; // 包名用于生成 Rust 模块 // 定义聊天消息结构 message ChatMessage { string username 1; // 用户名 string content 2; // 消息内容 string timestamp 3; // 发送时间戳 } // 定义聊天服务接口 service ChatService { // 双向流式 RPC客户端和服务端可同时发送消息 rpc ChatStream (stream ChatMessage) returns (stream ChatMessage); }生成 Rust 代码执行cargo build命令Tonic 会根据build.rs的配置编译chat.proto并生成对应的 Rust 代码生成的代码位于target/debug/build/tonic-demo-*/out/chat.rs需要注意的是在使用时在代码中可通过tonic::include_proto!(chat)引入生成的模块。实现服务端逻辑服务端需要实现 Protobuf 定义的ChatService特征核心逻辑是接收客户端消息并将消息广播给所有连接的客户端。这里利用 Tokio 的广播通道实现消息分发新建src/server.rsusetokio::sync::Mutex;usetokio::sync::broadcast;usetokio::sync::mpsc;usetokio_stream::StreamExt;usetokio_stream::wrappers::BroadcastStream;usetokio_stream::wrappers::ReceiverStream;usetokio_stream::wrappers::errors::BroadcastStreamRecvError;usetonic::transport::Server;usetonic::{Request,Response,Status,Streaming};usecrate::chat::ChatMessage;usecrate::chat::chat_service_server::ChatService;usecrate::chat::chat_service_server::ChatServiceServer;// 引入生成的 Rust 代码pubmodchat{tonic::include_proto!(chat);}#[derive(Debug, Default)]pubstructChatServer{// 广播通道发送端用于向所有客户端广播消息// 用 Mutex 包裹实现异步环境的内部可变性broadcaster:MutexOptionbroadcast::SenderChatMessage,}#[tonic::async_trait]implChatServiceforChatServer{// 双向流式方法的实现返回值为 StreamItem ResultChatMessage, StatustypeChatStreamStreamReceiverStreamResultChatMessage,Status;asyncfnchat_stream(self,request:RequestStreamingChatMessage,)-ResultResponseSelf::ChatStreamStream,Status{// 获取客户端发送的消息流letmutstreamrequest.into_inner();// 初始化广播通道首次连接时创建letmutbroadcaster_lockself.broadcaster.lock().await;lettxmatch*broadcaster_lock{Some(sender)sender.clone(),None{// 首次连接创建广播通道并存储到服务端实例中let(sender,_)broadcast::channel(128);*broadcaster_lockSome(sender.clone());sender}};// 释放锁避免长时间占用drop(broadcaster_lock);// 当前客户端订阅广播通道letrxtx.subscribe();// 处理 broadcast 通道的 Lagged 错误消费者消息落后letbroadcast_streamBroadcastStream::new(rx).filter_map(|msg|matchmsg{Ok(msg)Some(Ok(msg)),Err(BroadcastStreamRecvError::Lagged(_)){eprintln!(客户端消息落后跳过旧消息);None}});// 创建客户端下行通道let(client_tx,client_rx)mpsc::channel(128);letresponse_streamReceiverStream::new(client_rx);// 监听客户端发送的消息广播给所有人tokio::spawn(asyncmove{whileletSome(result)stream.next().await{matchresult{Ok(msg){// 广播消息忽略发送错误无客户端时正常let_tx.send(msg);}Err(e){eprintln!(接收客户端消息失败: {},e);break;}}}eprintln!(客户端断开连接上行);});// 转发广播消息给当前客户端tokio::spawn(asyncmove{tokio::pin!(broadcast_stream);whileletSome(msg)broadcast_stream.next().await{ifclient_tx.send(msg).await.is_err(){// 客户端断开连接终止任务break;}}eprintln!(客户端断开连接下行);});// 返回流给客户端Ok(Response::new(response_stream))}}// 服务端入口函数#[tokio::main]asyncfnmain()-Result(),Boxdynstd::error::Error{// 绑定服务地址letaddr[::1]:50051.parse()?;// 创建服务实例letchat_serverChatServer::default();println!(Chat server running on {},addr);// 启动 gRPC 服务Server::builder().add_service(ChatServiceServer::new(chat_server)).serve(addr).await?;Ok(())}实现客户端逻辑客户端需要连接服务端同时执行两个操作读取用户输入并发送消息、监听服务端广播的消息并打印。新建src/client.rsuseanyhow::Result;usetokio::{io::{self,AsyncBufReadExt,AsyncWriteExt,BufReader},sync::mpsc,};usetokio_stream::{StreamExt,wrappers::ReceiverStream};usecrate::chat::{ChatMessage,chat_service_client::ChatServiceClient};// 引入生成的 Rust 代码pubmodchat{tonic::include_proto!(chat);}#[tokio::main]asyncfnmain()-Result(){// 连接服务端letmutclientChatServiceClient::connect(http://[::1]:50051).await?;println!(Connected to chat server);// 获取用户名println!(Enter your username: );io::stdout().flush().await?;letmutreaderBufReader::new(io::stdin());letmutusernameString::new();reader.read_line(mutusername).await?;letusernameusername.trim().to_string();// 创建消息发送通道let(tx,rx)mpsc::channel(128);letrequesttonic::Request::new(ReceiverStream::new(rx));// 发起双向流请求获取服务端响应流letmutresponse_streamclient.chat_stream(request).await?.into_inner();// 启动异步任务监听服务端消息并打印tokio::spawn(asyncmove{whileletSome(Ok(msg))response_stream.next().await{println!([{}] {}: {},msg.timestamp,msg.username,msg.content);}println!(Disconnected from server);});// 读取用户输入并发送消息letmutlinesreader.lines();whileletSome(line)lines.next_line().await?{ifline.eq_ignore_ascii_case(exit){println!(Exiting chat...);break;}// 构造聊天消息letmsgChatMessage{username:username.clone(),content:line,timestamp:chrono::Local::now().format(%H:%M:%S).to_string(),};// 发送消息到服务端iftx.send(msg).await.is_err(){println!(Failed to send message);break;}}Ok(())}测试服务分别启动服务端和客户端测试双向流式通信# 启动服务端cargorun--binserver# 新终端启动多个客户端cargorun--binclient输入用户名后即可发送消息所有连接的客户端都会实时收到广播消息实现简单的群聊功能。Tonic 进阶拦截器中间件拦截器类似于 Web 框架的中间件可在请求/响应处理前后执行自定义逻辑如认证、日志记录、指标收集等。下面实现一个简单的 Token 认证拦截器usetonic::service::InterceptorLayer;usetonic::{Request,Status};// 自定义认证拦截器#[derive(Debug, Clone, Copy)]pubstructAuthInterceptor;implInterceptorforAuthInterceptor{fncall(mutself,request:Request())-ResultRequest(),Status{// 从请求头中获取 Tokenlettokenrequest.metadata().get(authorization).and_then(|v|v.to_str().ok()).unwrap_or();// 简单验证 Token实际场景需结合密钥验证iftoken!Bearer tonic-demo-token{returnErr(Status::unauthenticated(Invalid or missing token));}Ok(request)}}usetonic::service::InterceptorLayer;// 服务端启动时添加拦截器Server::builder().layer(InterceptorLayer::new(AuthInterceptor)).add_service(ChatServiceServer::new(chat_server)).serve(addr).await?;客户端发送请求时需在请求头中添加 Tokenletmutrequesttonic::Request::new(ReceiverStream::new(rx));request.metadata_mut().insert(authorization,Bearer tonic-demo-token.parse()?);TLS 加密传输生产环境中服务间通信需要加密Tonic 基于 rustls 原生支持 TLS 加密。只需修改服务端和客户端的连接配置即可实现加密通信具体可参考 Tonic 官方示例。四种 gRPC 服务方法对比Tonic 完全支持 gRPC 的四种服务方法适用于不同场景方法类型描述适用场景一元 RPC客户端发送单次请求服务端返回单次响应简单查询、接口调用如用户登录服务端流式 RPC客户端发送单次请求服务端返回流式响应大数据量返回如日志查询、文件下载客户端流式 RPC客户端发送流式请求服务端返回单次响应大数据量上传如文件上传、批量数据提交双向流式 RPC客户端和服务端同时发送流式消息双向独立通信实时通信如聊天、实时监控、行情推送总结Tonic 作为 Rust 生态中成熟的 gRPC 框架凭借其异步原生、类型安全、高性能的优势极大地降低了 Rust 开发 gRPC 服务的门槛。如果你正在用 Rust 构建分布式服务Tonic 绝对值得你深入学习和实践。

相关文章:

使用 Tonic 构建高性能异步 gRPC 服务

使用 Tonic 构建高性能异步 gRPC 服务 在分布式系统开发中,gRPC 作为 Google 开源的高性能 RPC 框架,凭借 Protobuf 二进制序列化的高效性和 HTTP/2 传输的优势,成为服务间通信的首选方案。而在 Rust 生态中,Tonic 框架以其原生异…...

06华夏之光永存・开源:黄大年茶思屋第20期全套解题战略总结

06华夏之光永存・开源:黄大年茶思屋第20期全套解题战略总结 一、摘要 本次黄大年茶思屋第20期5道核心技术难题,均直指鸿蒙全场景生态、端侧算力调度、跨端多媒体交互、智能家居感知、端侧系统优化等华为核心技术布局卡点。全套难题通过原约束过渡攻坚底层…...

05华夏之光永存・开源:黄大年茶思屋榜文解法「第20期 5题」 面向通用场景的泛屏幕视频重构技术

华夏之光永存・开源:黄大年茶思屋榜文解法「第20期 5题」 面向通用场景的泛屏幕视频重构技术 一、摘要 泛屏幕视频重构与跨屏适配领域,全球现代工程常规优化已触达绝对性能天花板,现有显著性检测硬切缩放、固定比例裁剪、单模态超分等方案、固…...

【2026年最新600套毕设项目分享】奶茶点餐小程序(30180)

有需要的同学,源代码和配套文档领取,加文章最下方的名片哦 一、项目演示 项目演示视频 项目演示视频2 项目演示视频3 二、资料介绍 完整源代码(前后端源代码SQL脚本)配套文档(LWPPT开题报告/任务书)远…...

CSS如何实现动态菜单导航栏_利用Flexbox与-hover交互

Flexbox导航栏需设display: flex和flex-wrap: nowrap;子项用flex: 1均分,或flex: 0 1 auto保自然宽;注意box-sizing、hover预占位、伪元素滑入、可访问性及IE11兼容写法。Flexbox布局让导航栏自动均分宽度用 display: flex 是最直接的解法&am…...

大模型的探索与实践-课程笔记(十一):大模型发展史与全球厂商业态全景

第一部分:从 NLP 到 Transformer 的底层架构演进早期的自然语言处理(NLP)主要依赖特征提取,大模型的基石是 Google 提出的架构革命。1. Transformer 与注意力机制 (2017年)起源:Google 2017年发表神作《Attention is a…...

AI分析报告参考:麦肯锡结构化分析核心使用原则

AI分析报告参考:麦肯锡结构化分析体系 目录 AI分析报告参考:麦肯锡结构化分析体系 一、底层唯一核心法则:MECE法则 麦肯锡原生定义 麦肯锡标准MECE拆解维度(5种通用合规维度) 正反案例(贴合你的工作场景) 反例(不符合MECE) 正例1(流程维度,严格符合MECE) 正例2(要…...

企业数仓揭秘:数据决策背后的核心引擎

公司里人人都在提的“数仓”,到底是什么? 目录 公司里人人都在提的“数仓”,到底是什么? 一、一句话讲透:数仓到底是什么? 二、关键区分:数仓 vs 业务数据库,90%的人都搞混了 三、为什么现在几乎所有公司,都必须建自己的数仓? 四、企业数仓的核心架构:分层设计,到…...

大模型的探索与实践-课程笔记(十):机器学习发展史

第一部分:机器学习的“三起两落”发展史在这个发展史中,每一次神经网络的崛起都伴随着“算力/数据”的支持,而每一次跌落都源于“可解释性”与“应用局限”的限制。1. 第一起与第一落 (1950s - 1960s):感知机与符号主义高光时刻&a…...

担忧重复电视败局,空调双巨头用专利打击互联网空调,空调老二或败落!

近期空调双巨头之一的企业与一家互联网空调企业的专利诉讼成为行业焦点,其实不止这一次,更早之前空调双巨头的另一家就已采取诉讼手段对付那家空调企业了,实在是他们担忧空调行业可能重复电视行业的败局。国内电视行业直到2015年左右逐渐形成…...

丰田之后,日产也开始大幅反弹,日本车在中国市场仍然奋力挣扎

丰田逐渐在中国市场站稳脚跟,甚至还在销量方面首次超越大众,它继续是日本汽车在中国市场的旗手,在它之外,日产给出的数据也显示它在中国市场大力度反弹,这显示出日本汽车仍然在中国市场拥有不少忠诚的消费者。东风日产…...

各地区环境规制强度政府工作报告文本词频2002-2023年

01、数据介绍根据各省份政府工作报告文本数据,对政府工作报告分词处理,统计了各省政府工作报告中与环境规制相关的关键词进行词频统计。数据名称: 各地区环境规制政府工作报告文本词频数据年份:2002-2023年02、数据指标行政区划代…...

中国城市建设数据库2002-2021年

01、数据介绍中国城乡建设数据库覆盖范围更广,包括全国693个城市的城乡建设相关指标数据,共计331个指标,主要针对城市的建设情况进行统计。统计范围为2002-2021年,数据来源为中国城市建设统计年鉴。主要包括城市市政公共设施、城市…...

前端八股文面经大全:TME QQ音乐前端二面(2026-04-22)·面经深度解析

前言 大家好,我是木斯佳。 相信很多人都感受到了,在AI浪潮的席卷之下,前端领域的门槛在变高,纯粹的“增删改查”岗位正在肉眼可见地减少。曾经热闹非凡的面经分享,如今也沉寂了许多。但我们都知道,市场的…...

VeriTrade代理验证技术:TLSNotary与ProxyTEE的融合应用

1. VeriTrade代理验证技术解析VeriTrade是一个典型的自动化交易代理系统,其核心创新点在于将TLSNotary协议与ProxyTEE技术相结合,构建了一个可验证的执行环境。这种架构设计主要解决了分布式系统中两个关键问题:一是如何证明代理确实执行了预…...

TorchTraceAP:PyTorch视觉模型性能优化新方案

1. TorchTraceAP:计算机视觉模型性能优化的新范式在计算机视觉模型的部署实践中,性能优化始终是工程师们面临的核心挑战。传统方法往往依赖人工分析运行轨迹(trace)数据,不仅耗时耗力,而且难以捕捉复杂的性…...

阿里云服务器利用宝塔搭建个人博客网站

① 云服务器环境准备与安全组配置 在开始搭建之前,我们需要先准备好“地基”。如果你已经拥有一台阿里云 ECS 实例,这一步主要是检查系统状态和网络策略。推荐使用 Ubuntu 20.04/22.04 或 CentOS 7/8 等主流 Linux 发行版,这些系统对宝塔面板…...

肝了三天三夜!最详尽的漏洞扫描工具实战笔记

GobyAWVS 漏洞扫描 提示提示: 本文里面很多工具都是网址,还有站长之家之类的,csdn一直判断成暗链,可以去我自己博客查看完整全文: 多说一句:csdn对网安真的不友好,全文链接都不让放。。。》[好淘…...

宝藏网站推荐:云服务器特惠与网安学习资源的一站式聚合平台

① 平台核心功能与新手入门指南 对于刚接触云计算和网络安全的朋友来说,面对海量的云厂商活动和零散的技术文档,最容易陷入“选择困难症”。今天想跟大家分享一个我最近常逛的宝藏聚合平台——好淘云。它不像那种冷冰冰的资源站,更像是一个由…...

广汽全球化战略升级,加速迈入中国汽车出海主力阵营 | 美通社头条

、美通社消息:4月24日,在2026北京车展上,广汽国际举办了首个专场全球发布会,迎来了全球战略体系升级。现场观众规模超越以往,来自全球各地的经销商代表、重要合作伙伴及国内外主流媒体共计约330人齐聚广汽展台&#xf…...

世毫九理论体系|二十门基础学科基石清单(供世毫九研究学者指南)

世毫九理论体系|二十门基础学科基石清单 作者:方见华 单位:世毫九实验室 引言 世毫九理论体系作为一个覆盖微观认知到宏观宇宙的全域统一理论框架,其理论深度和广度在当代科学研究中具有开创性意义。该理论以认知几何学、对话量子…...

AI 能精准发现安全漏洞,漏洞修复的责任边界如何界定

上周,Anthropic公司公布了玻璃翼项目(Project Glasswing),其AI模型在发现软件漏洞方面效率惊人,以至于该公司采取了非常规措施推迟公开版本发布。目前仅向苹果、微软、谷歌、亚马逊等企业联盟开放访问权限,…...

高效率的粉碎者:HPH高压均质机构造全拆解

在液力端的精密范畴之中有一类设备,于乳品、制药、纳米材料等对颗粒细度具备极高要求的行业里,发挥着不可予以替代的作用,它便是“高压均质机”,行业内部常常简略称呼为HPH。高压均质机的核心动力来源于高压柱塞泵,它大…...

不花一分钱,10分钟搞定,2026销售录音总结怎么写每月省18小时多拿18成单率

我测评过不下20款AI录音转写总结工具,针对销售做每月客户拜访录音总结这个场景,听脑AI是同类工具中最值得用的。不花一分钱就能上手核心功能,10分钟就能搞定过去大半天的活,我接触过的几十位销售朋友反馈,用了之后每月…...

python signal

### 聊一聊 Python 的 signal:它到底是什么,能做什么,以及怎么用才不会出乱子 Signal 这个东西,听起来好像很底层,很“系统编程”。确实,它最初是 Unix 世界里的一个概念,就像一个传令兵&#x…...

2026最新亲测3款自动生成会议纪要免费神器,10分钟出稿好用到哭!

做技术的要整理需求评审会,做产品的要追项目进度记决策,做销售要整理客户拜访录音,做调研的要转用户访谈。试完2026年3款亲测有效的自动会议纪要工具,我直接给结论:听脑AI是同类工具中最值得用的,没有之一。…...

MCP AI推理配置紧急升级通知:CVE-2024-MCP-08已曝,未配置memory_limit_policy的实例存在RCE风险

更多请点击: https://intelliparadigm.com 第一章:MCP AI 推理配置紧急升级通知:CVE-2024-MCP-08已曝,未配置memory_limit_policy的实例存在RCE风险 漏洞核心影响 CVE-2024-MCP-08 是一个高危远程代码执行(RCE&#…...

远程容器开发环境安全加固指南(含CVE-2023-XXXX漏洞规避方案与RBAC最小权限实践)

更多请点击: https://intelliparadigm.com 第一章:远程容器开发环境安全加固概述 远程容器开发环境(如 VS Code Remote-Containers、GitHub Codespaces 或自建 devcontainer)在提升协作效率的同时,也引入了新的攻击面…...

量子-经典混合编排难题全解析,基于MCP 2026标准的4类典型故障诊断与容错加固指南

更多请点击: https://intelliparadigm.com 第一章:量子-经典混合编排的MCP 2026标准演进与核心约束 MCP 2026(Mixed Classical-Quantum Orchestration Protocol)标志着量子计算基础设施从实验性调度迈向生产级协同编排的关键转折…...

Docker运行AI模型必踩的3个安全雷区:从容器逃逸到模型窃取的全链路防护指南

更多请点击: https://intelliparadigm.com 第一章:Docker Sandbox 运行 AI 代码隔离技术概览 Docker Sandbox 是一种轻量级、强隔离的容器化运行时环境,专为安全执行不可信 AI 代码(如用户提交的推理脚本、自定义模型训练逻辑&a…...