GolangRPC流式传输与双向通信示例

Golang gRPC双向流式传输支持实时交互,通过定义protobuf服务、生成代码、实现服务器和客户端完成通信,示例中客户端发送消息服务器回显;需处理流中错误,可采用重试或断路器模式;通过TLS和JWT实现身份验证与授权;性能优化包括启用压缩、调整缓冲区、使用连接池、负载均衡及HTTP/3协议提升传输效率。

golangrpc流式传输与双向通信示例

Golang gRPC 流式传输允许客户端和服务器之间进行连续的数据交换,而不仅仅是传统的请求-响应模式。双向流式传输则允许双方同时发送和接收数据,极大地增强了实时性和交互性。

解决方案

下面是一个简单的 Golang gRPC 双向流式传输的示例。

1. 定义 Protocol Buffer (protobuf) 服务

立即学习“go语言免费学习笔记(深入)”;

首先,我们需要定义一个 protobuf 文件,描述我们的服务和消息格式。

syntax = "proto3";package stream;option go_package = "./stream";service StreamService {  rpc RouteChat (stream RouteNote) returns (stream RouteNote) {}}message RouteNote {  string message = 1;}

这个protobuf文件定义了一个

StreamService

服务,其中包含一个

RouteChat

方法。

RouteChat

方法接受并返回

RouteNote

类型的流。

2. 生成 gRPC 代码

使用

protoc

命令编译 protobuf 文件,生成 Golang 代码。

protoc --go_out=. --go-grpc_out=. stream.proto

这将生成

stream.pb.go

stream_grpc.pb.go

文件。

3. 实现 gRPC 服务器

接下来,我们需要实现 gRPC 服务器。

package mainimport (    "context"    "fmt"    "io"    "log"    "net"    "google.golang.org/grpc"    "google.golang.org/grpc/reflection"    pb "example.com/stream" // 替换成你的模块路径)type server struct {    pb.UnimplementedStreamServiceServer}func (s *server) RouteChat(stream pb.StreamService_RouteChatServer) error {    for {        note, err := stream.Recv()        if err == io.EOF {            return nil        }        if err != nil {            return err        }        log.Printf("Received message: %v", note.Message)        // Echo back the message        resp := &pb.RouteNote{Message: "Server received: " + note.Message}        if err := stream.Send(resp); err != nil {            return err        }    }}func main() {    lis, err := net.Listen("tcp", ":50051")    if err != nil {        log.Fatalf("failed to listen: %v", err)    }    s := grpc.NewServer()    pb.RegisterStreamServiceServer(s, &server{})    reflection.Register(s)    fmt.Println("Server listening on :50051")    if err := s.Serve(lis); err != nil {        log.Fatalf("failed to serve: %v", err)    }}

这段代码创建了一个 gRPC 服务器,监听 50051 端口,并注册了

StreamService

服务。

RouteChat

方法循环接收客户端发送的消息,并将带有 “Server received: ” 前缀的消息回传给客户端。

4. 实现 gRPC 客户端

现在,我们需要实现 gRPC 客户端。

package mainimport (    "context"    "fmt"    "io"    "log"    "time"    "google.golang.org/grpc"    "google.golang.org/grpc/credentials/insecure"    pb "example.com/stream" // 替换成你的模块路径)func main() {    conn, err := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))    if err != nil {        log.Fatalf("did not connect: %v", err)    }    defer conn.Close()    client := pb.NewStreamServiceClient(conn)    stream, err := client.RouteChat(context.Background())    if err != nil {        log.Fatalf("could not greet: %v", err)    }    // Send messages    messages := []string{"Hello", "World", "How", "Are", "You"}    for _, message := range messages {        req := &pb.RouteNote{Message: message}        if err := stream.Send(req); err != nil {            log.Fatalf("failed to send a note: %v", err)        }        log.Printf("Sent message: %v", message)        time.Sleep(time.Second) // Simulate some delay    }    // Close the stream and receive responses    if err := stream.CloseSend(); err != nil {        log.Fatalf("failed to close stream: %v", err)    }    for {        resp, err := stream.Recv()        if err == io.EOF {            break        }        if err != nil {            log.Fatalf("failed to receive a note: %v", err)        }        log.Printf("Received message: %v", resp.Message)    }    fmt.Println("Client finished")}

这段代码连接到 gRPC 服务器,创建

StreamService

客户端,并调用

RouteChat

方法。客户端发送一系列消息,然后关闭发送流,并接收服务器返回的消息。

5. 运行示例

首先,启动 gRPC 服务器。

go run server.go

然后,启动 gRPC 客户端。

go run client.go

你将在服务器和客户端的控制台中看到消息的发送和接收。

如何处理 gRPC 流中的错误?

在流式传输中,错误处理至关重要。服务器和客户端都需要能够优雅地处理连接中断、数据损坏或其他意外情况。在服务器端,

RouteChat

函数的循环中,我们检查

stream.Recv()

stream.Send()

的返回值,如果遇到错误,则立即返回。客户端也做了类似的错误处理。 更复杂的错误处理可能涉及到自定义错误类型、重试机制或断路器模式。例如,可以定义一个专门的错误类型,用于表示流式传输中的特定错误,并根据错误类型采取不同的处理策略。

如何在 gRPC 流中进行身份验证和授权?

安全性是另一个需要考虑的重要方面。gRPC 提供了多种身份验证机制,例如 TLS、JWT 和自定义身份验证。对于流式传输,通常使用 TLS 来加密通信,并使用 JWT 或其他身份验证方法来验证客户端的身份。服务器可以在

RouteChat

函数中验证客户端提供的身份验证信息,并根据用户的角色和权限来决定是否允许客户端访问资源。例如,可以创建一个 gRPC 拦截器,用于在每个流式请求上验证 JWT 令牌。

如何优化 gRPC 流的性能?

gRPC 流的性能受到多种因素的影响,例如网络延迟、消息大小和服务器的负载。为了优化性能,可以采取以下措施:

使用压缩: 启用 gRPC 的压缩功能可以减少消息的大小,从而提高传输速度。调整缓冲区大小: 调整 gRPC 的发送和接收缓冲区大小可以优化内存使用和吞吐量。使用连接池: 使用连接池可以减少连接建立的开销,从而提高性能。负载均衡: 使用负载均衡可以将请求分发到多个服务器上,从而提高系统的可用性和可扩展性。协议选择: 考虑使用 HTTP/3 协议,它在拥塞控制和多路复用方面提供了改进,尤其是在高延迟或丢包的网络环境下。HTTP/3 默认使用 QUIC 协议,提供更好的连接迁移能力。

例如,可以通过设置

grpc.WithDefaultCallOptions(grpc.UseCompressor(gzip.Name))

来启用 gzip 压缩。

以上就是GolangRPC流式传输与双向通信示例的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1403579.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月15日 19:43:17
下一篇 2025年12月15日 19:43:24

相关推荐

  • Golang macOS系统下GoLand配置技巧

    首先确保Go SDK路径正确,手动配置GOROOT指向/usr/local/go或Homebrew安装路径;接着在Preferences中设置Go Modules、GOPROXY加速依赖下载;启用File Watchers实现保存时自动格式化代码;合理添加插件并排除无关目录以优化性能;最后通过Inv…

    好文分享 2025年12月15日
    000
  • Golang数据库驱动安装与连接方法

    答案:Golang中安装和连接数据库需使用database/sql库配合驱动,如MySQL用go get github.com/go-sql-driver/mysql并匿名导入,通过sql.Open和DSN建立连接,db.Ping()验证;连接池通过SetMaxOpenConns、SetMaxIdl…

    2025年12月15日
    000
  • Golang API文档生成 Swagger集成指南

    使用Swag工具可实现Golang API文档自动化生成与Swagger UI集成。首先通过go install安装Swag,随后在Go代码的Handler函数上添加Swag注释(如@Summary、@Param、@Success等),描述API元信息。接着运行swag init命令,自动生成doc…

    2025年12月15日
    000
  • Golang减少内存碎片提高运行效率

    Golang通过sync.Pool对象重用、strings.Builder减少字符串拼接、预分配切片和map、自定义内存分配器、优化堆分配及逃逸分析等方法减少内存碎片,结合runtime监控和pprof分析,辅以操作系统大页内存、容器化隔离和定期重启等手段,可有效提升内存使用效率和程序性能。 Gol…

    2025年12月15日
    000
  • Golang在K8s集群中服务注册与发现

    K8s中Go微服务通过Pod标签与Service selector匹配实现自动注册,结合健康检查确保流量仅导向就绪实例;服务发现主要依赖CoreDNS提供的DNS解析,Go程序可直接通过服务名访问,如http://service.namespace.svc.cluster.local,或使用环境变量…

    2025年12月15日
    000
  • Golang实战中如何将结构体(struct)序列化为JSON字符串返回

    Go语言通过json.Marshal将结构体序列化为JSON,需字段首字母大写并配合json标签;支持omitempty省略空字段、嵌套结构体及time.Time类型,默认输出RFC3339时间格式,可通过json.NewEncoder直接写入HTTP响应,高效返回JSON数据。 在Go语言开发中,…

    2025年12月15日
    000
  • Golang反射动态构建结构体与赋值实践

    反射可动态操作变量类型与值,通过reflect.Type获取类型信息,reflect.Value操作具体值,用于创建结构体、设字段值及调用方法。 在Go语言中,反射(reflect)是一种强大的机制,允许程序在运行时动态地查看和操作变量的类型与值。通过反射,我们可以在不知道具体类型的情况下创建结构体…

    2025年12月15日
    000
  • Golang错误处理与缓存操作 处理缓存击穿与雪崩

    Go语言通过显式返回error和defer-recover机制实现错误处理,强调调用方主动判断错误;针对缓存击穿,采用加锁重建、逻辑过期或本地缓存避免瞬时压力;为防缓存雪崩,设置随机过期时间、构建Redis集群、实施限流降级与异步预热;结合context超时控制与重试机制可提升系统稳定性,击穿重单点…

    2025年12月15日
    000
  • 在Golang Web项目中如何实现一个简单的日志记录中间件

    日志中间件通过包装http.Handler记录请求信息,可实现请求路径、方法、响应状态码和处理时间的自动日志输出,支持标准输出或文件写入,提升Go Web项目调试与监控能力。 在Golang Web项目中,日志记录中间件可以帮助我们自动记录每次HTTP请求的基本信息,比如请求路径、方法、响应状态码、…

    2025年12月15日
    000
  • Golangchannel模式优化与性能提升技巧

    答案:选择合适的Golang Channel类型需权衡同步与缓冲,无缓冲Channel适用于强同步场景,缓冲Channel提升吞吐量但需合理设置容量,避免资源浪费和性能瓶颈。 Golang channel的优化核心在于理解其并发原语的特性,并根据具体场景选择合适的模式,以平衡吞吐量、延迟与资源消耗。…

    2025年12月15日
    000
  • Golang反射在日志记录中的应用技巧

    答案是使用反射可自动打印结构体字段。通过reflect.ValueOf和reflect.TypeOf获取变量的值和类型,若为指针则解引用,再遍历结构体字段,获取字段名和值,实现通用日志输出,提升调试效率与代码可维护性。 在Go语言开发中,日志记录是调试和监控系统运行状态的重要手段。当结构体字段较多或…

    2025年12月15日
    000
  • Golangpanic与recover异常处理机制

    Go语言通过panic和recover处理严重错误,而非try-catch。panic触发运行时恐慌,中断函数执行并触发defer调用;recover在defer中捕获panic以恢复执行。例如safeDivide中用defer+recover捕获除零panic并转为error返回。该机制仅用于不可…

    2025年12月15日
    000
  • GolangDevOps中服务健康检查与监控

    Go服务健康检查需区分/ready和/health接口,分别判断服务就绪与存活状态;02. 结合Prometheus采集指标如请求量、goroutine数,并暴露/metrics端点;03. 集成zap日志与OpenTelemetry链路追踪,关联trace ID定位故障;04. 通过Alertma…

    2025年12月15日
    000
  • Golangdefer延迟执行机制与使用场景

    Go语言中defer关键字用于延迟执行函数,确保资源释放、锁的释放及panic恢复。1. defer按后进先出顺序执行,参数在声明时求值;2. 常用于文件关闭、互斥锁释放和错误恢复;3. 注意避免在循环中滥用defer,防止性能下降。 Go语言中的defer关键字用于延迟函数或方法的执行,直到包含它…

    2025年12月15日
    000
  • Golang macOS系统环境搭建及常见问题解决

    答案:使用Homebrew安装Go并配置PATH和GOPATH环境变量,通过go version和go env验证,推荐VS Code或GoLand进行开发并掌握调试技巧。 在macOS上搭建Golang开发环境,其实并不复杂,核心就是下载Go SDK,然后确保你的系统能找到它。多数情况下,这涉及到…

    2025年12月15日
    000
  • Golang初级HTTP请求处理项目案例

    答案:从创建简易待办事项API入手,使用Go语言实现获取所有事项、添加新事项及标记完成状态功能,通过定义Todo结构体与内存切片模拟数据存储,结合net/http包处理路由与JSON响应,适合初学者快速掌握Golang HTTP服务基础。 想快速上手 Golang 的 HTTP 请求处理?从一个简单…

    2025年12月15日
    000
  • Golang单元测试中常用辅助函数设计

    设计测试辅助函数的核心是提升可读性、可维护性和效率,通过封装重复逻辑如环境初始化、通用断言、数据生成和模拟依赖,让测试聚焦业务逻辑。使用t.Helper()和t.Cleanup()确保错误定位准确和资源释放,遵循单一职责、可配置性及避免过度抽象,防止增加理解成本。辅助函数应简洁实用,仅在真正简化代码…

    2025年12月15日
    000
  • Golang入门项目中数据库操作实战

    答案:掌握Golang操作MySQL需完成连接、建表、增删改查和预编译。先用database/sql和go-sql-driver/mysql驱动连接数据库,定义结构体映射表字段,通过Exec和Query执行增删改查,使用Prepare预编译提升安全与性能,原生sql包足够项目初期使用。 刚接触Gol…

    2025年12月15日
    000
  • Golang字符串操作常用方法与示例

    Go语言中字符串不可变,常用操作包括:1. strings.Contains判断子串;2. Split分割,Join拼接;3. Replace替换;4. ToUpper/ToLower转换大小写;5. TrimSpace去除空白;6. strconv实现字符串与数字转换,频繁拼接建议用strings…

    2025年12月15日
    000
  • Golang常量定义及使用方法详解

    Go语言中使用const定义不可变值,提升代码安全与可读性;支持单个、批量定义及iota枚举,如const Pi = 3.14、const (A=1 B C)和const (Red=iota Green Blue)。 在Go语言中,常量是程序运行期间不可改变的值。它们用于定义固定的数据,比如数学常数…

    2025年12月15日
    000

发表回复

登录后才能评论
关注微信