gRPC原生支持四种通信模式:Unary、Server Streaming、Client Streaming和Bidirectional Streaming。其中流式RPC适合大数据量、高实时性场景,能避免内存溢出、降低延迟、提升吞吐,并支持服务端推送与客户端持续发送。
gRPC 原生支持四种通信模式,其中流式 RPC(Streaming RPC)特别适合处理大数据量、实时性要求高或需要持续交互的场景。相比传统的一次请求-响应模型,流式传输能避免内存溢出、减少延迟、提升吞吐,并支持服务端推送、客户端持续发送等灵活交互方式。
gRPC 定义了以下四种流式通信方式,全部基于 HTTP/2 的多路复用和双向数据帧能力:
关键在于在 .proto 文件中使用 stream 关键字声明流式方法。例如实现一个双向流式日志转发服务:
syntax = "proto3"; package logsvc;service LogService { // 双向流:客户端发送日志条目,服务端可实时反馈确认或过滤结果 rpc StreamLogs(stream LogEntry) returns (stream LogResponse); }
message LogEntry { string level = 1; string message = 2; int64 timestamp = 3; }
message LogResponse { bool accepted = 1; string id = 2; string reason = 3; }
执行生成命令(需安装 protoc 和 protoc-gen-go、protoc-gen-go-grpc):
protoc --go_out=. --go-grpc_out=. --go-grpc_opt=paths=source_relative logsvc.proto
生成的 Go 接口会包含 StreamLogs 方法,其参数为 LogService_StreamLogsServer(服务端)或 LogService_StreamLogsClient(客户端),均实现了 Recv()/Send() 等流控方法。
服务端需在一个 goroutine 中持续读取客户端消息,同时可随时写入响应。注意错误处理与连接生命周期管理:
func (s *logServer) StreamLogs(stream logsvc.LogService_StreamLogsServer) error{ for { req, err := stream.Recv() if err == io.EOF { return nil // 客户端关闭流 } if err != nil { return status.Errorf(codes.Unknown, "recv failed: %v", err) }
// 处理单条日志(例如写入 Kafka、校验格式、异步落盘) resp := &logsvc.LogResponse{ Accepted: true, Id: fmt.Sprintf("log-%d", time.Now().UnixNano()), } // 异步响应(不阻塞接收)——可配合 select + channel 控制背压 if err := stream.Send(resp); err != nil { return status.Errorf(codes.Unavailable, "send failed: %v", err) }} }
⚠️ 注意:
Recv()是阻塞调用;若需并发处理(如批量聚合后再响应),建议将接收的消息发到内部 channel,由 worker goroutine 消费。客户端发起流式调用(Go)
客户端同样使用
Send()和Recv(),但顺序和节奏由业务决定。例如模拟持续发送日志:conn, _ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials())) defer conn.Close() client := logsvc.NewLogServiceClient(conn)stream, _ := client.StreamLogs(context.Background()) defer stream.CloseSend() // 发送端关闭,通知服务端“不再发了”
// 并发发送日志(可控制速率) go func() { for i := 0; i < 100; i++ { entry := &logsvc.LogEntry{ Level: "INFO", Message: fmt.Sprintf("log #%d", i), Timestamp: time.Now().Unix(), } if err := stream.Send(entry); err != nil { log.Printf("send error: %v", err) return } time.Sleep(10 * time.Millisecond) // 模拟节流 } }()
// 同时接收服务端响应 for { resp, err := stream.Recv() if err == io.EOF { break } if err != nil { log.Printf("recv error: %v", err) break } log.Printf("Got response: %+v", resp) }
? 小技巧:用
context.WithTimeout或WithCancel控制整个流生命周期;对超大数据流,可结合runtime.GC()或debug.FreeOSMemory()(谨慎使用)缓解内存压力。基本上就这些。流式 RPC 不是魔法,核心在于理解流的边界(何时 EOF)、错误传播机制(单次 Send/Recv 失败是否终止整个流)、以及如何与业务逻辑解耦(比如用 channel 缓冲、用 worker 池处理)。只要协议定义清晰、流控得当,gRPC 流完全能扛住 GB 级日志、百万级 IoT 设备心跳或实时音视频元数据同步。
# go # golang # 大数据 # ai # unix # stream # red # EOF # 接口 # 并发 # channel # 异步 # http # rpc # iot # 服务端 # 客户端 # 流式 # 四种 # 多个 # 均可 # 发了 # 最常见 # 音视频 # 关键在于
相关文章: 如何选择PHP开源工具快速搭建网站? 商务网站制作工程师,从哪几个方面把握电子商务网站主页和页面的特色设计? 如何在Golang中处理模块冲突_解决依赖版本不兼容问题 武清网站制作公司,天津武清个人营业执照注销查询系统网站? 网站制作知乎推荐,想做自己的网站用什么工具比较好? 建站之星如何助力网站排名飙升?揭秘高效技巧 广州网站制作的公司,现在专门做网站的公司有没有哪几家是比较好的,性价比高,模板也多的? 北京网站制作公司哪家好一点,北京租房网站有哪些? 网站制作员失业,怎样查看自己网站的注册者? 三星网站视频制作教程下载,三星w23网页如何全屏? 建站之星代理如何获取技术支持? XML的“混合内容”是什么 怎么用DTD或XSD定义 山东网站制作公司有哪些,山东大源集团官网? 唐山网站制作公司有哪些,唐山找工作哪个网站最靠谱? 香港服务器建站指南:免备案优势与SEO优化技巧全解析 合肥制作网站的公司有哪些,合肥聚美网络科技有限公司介绍? 建站之星如何实现网站加密操作? 如何通过免费商城建站系统源码自定义网站主题与功能? 如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗? 青浦网站制作公司有哪些,苹果官网发货地是哪里? 如何确保西部建站助手FTP传输的安全性? 大连企业网站制作公司,大连2025企业社保缴费网上缴费流程? 建站为何优先选择香港服务器? 齐河建站公司:营销型网站建设与SEO优化双核驱动策略 建站之星导航配置指南:自助建站与SEO优化全解析 个人摄影网站制作流程,摄影爱好者都去什么网站? 小捣蛋自助建站系统:数据分析与安全设置双核驱动网站优化 手机怎么制作网站教程步骤,手机怎么做自己的网页链接? c++怎么编写动态链接库dll_c++ __declspec(dllexport)导出与调用【方法】 ,购物网站怎么盈利呢? 建站主机解析:虚拟主机配置与服务器选择指南 广州美橙建站如何快速搭建多端合一网站? 如何在阿里云域名上完成建站全流程? 高防服务器租用指南:配置选择与快速部署攻略 如何用狗爹虚拟主机快速搭建网站? 如何通过虚拟机搭建网站?详细步骤解析 企业微网站怎么做,公司网站和公众号有什么区别? 电脑免费海报制作网站推荐,招聘海报哪个网站多? 杭州银行网站设计制作流程,杭州银行怎么开通认证方式? 如何优化Golang Web性能_Golang HTTP服务器性能提升方法 网站制作公司排行榜,抖音怎样做个人官方网站 网站制作壁纸教程视频,电脑壁纸网站? 盘锦网站制作公司,盘锦大洼有多少5G网站? 建站之星下载版如何获取与安装? 济南企业网站制作公司,济南社保单位网上缴费步骤? 建站主机如何选?高性价比方案全解析 如何基于云服务器快速搭建网站及云盘系统? 简历在线制作网站免费,免费下载个人简历的网站是哪些? 常州自助建站工具推荐:低成本搭建与模板选择技巧 网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?
*请认真填写需求信息,我们会在24小时内与您取得联系。