返回顶部
首页 > 资讯 > 后端开发 > GO >Go语言Grpc Stream的实现
  • 892
分享到

Go语言Grpc Stream的实现

2024-04-02 19:04:59 892人浏览 泡泡鱼
摘要

目录Stream grpcStream Grpc演示BookListStreamCreateBookStreamFindBookByIdStreamStream Grpc 在我们单次

Stream Grpc

在我们单次投递的数据量很大的时候,比如传输一个二进制文件的时候,数据包过大,会造成瞬时传输压力。或者接收方接收到数据后,需要对数据做一系列的处理工作,

比如:数据过滤 -> 数据格式转换 -> 数据求和 ,这种场景非常适合使用stream grpc,

Stream Grpc演示

syntax = "proto3";

package book_stream;

option Go_package = "/book_stream";

service HelloStreamService {
  rpc BookListStream(BookListStreamRequest) returns (stream BookListStreamResponse){};
  rpc CreateBookStream(stream CreateBookStreamRequest) returns (CreateBookStreamResponse){}
  rpc FindBookByIdStream(stream FindBookByIdStreamRequest) returns (stream FindBookByIdStreamResponse){}
}

message BookListStreamRequest{
}

message BookListStreamResponse{
  BookPoint book = 1;
}

message CreateBookStreamRequest{
  BookPoint book = 1;
}

message CreateBookStreamResponse{
  repeated BookIdPoint idx = 1;
}

message FindBookByIdStreamRequest{
  BookIdPoint idx = 1;
}
message FindBookByIdStreamResponse{
  BookPoint book = 1;
}

message BookIdPoint{
  uint64 idx = 1;
}

message BookPoint{
  uint64 idx = 1;
  string name = 2;
  float price = 3;
  string author = 4;
}

运行protoc --go_out=plugins=grpc:. *.proto生成脚手架文件

  • BookListStream服务端流式RPC
  • CreateBookStream客户端流式RPC
  • FindBookByIdStream双向流式RPC

注意,这里只是用作方便演示使用,演示方法都不是线程安全

服务端server

var port = 8888

func main() {
   server := grpc.NewServer()
   book_stream.ReGISterHelloStreamServiceServer(server, new(HelloStreamServiceImpl))
   lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
   if err != nil {
      panic(err)
   }
   if err := server.Serve(lis); err != nil {
      panic(err)
   }
}

客户端

func main() {
   var port = 8888
   conn, err := grpc.Dial(fmt.Sprintf(":%d", port), grpc.WithInsecure())
   if err != nil {
      panic(err)
   }
   defer conn.Close()
   client := book_stream.NewHelloStreamServiceClient(conn)

   ctx := context.Background()
   if err := createBookStream(ctx, client); err != nil {
      panic(err)
   }
   if err := printBookList(ctx, client); err != nil {
      panic(err)
   }
   if err := getBookListById(ctx, client); err != nil {
      panic(err)
   }
}

BookListStream

服务器端流式 RPC,显然是单向流,并代指 Server 为 Stream 而 Client 为普通 RPC 请求

简单来讲就是客户端发起一次普通的 RPC 请求,服务端通过流式响应多次发送数据集,客户端 Recv 接收数据集。

server端实现


var bookStore = map[uint64]book_stream.BookPoint{
   1: {
      Idx:    1,
      Author: "程子",
      Price:  9.9,
      Name:   "游戏思维",
   },
   2: {
      Idx:    2,
      Author: "丁锐",
      Price:  9.9,
      Name:   "活出必要的锋芒",
   },
}


type HelloStreamServiceImpl struct{}

func (HelloStreamServiceImpl) BookListStream(_ *book_stream.BookListStreamRequest, streamServer book_stream.HelloStreamService_BookListStreamServer) error {
   for idx, bookPoint := range bookStore {
      err := streamServer.Send(&book_stream.BookListStreamResponse{Book: &book_stream.BookPoint{
         Idx:    idx,
         Name:   bookPoint.Name,
         Price:  bookPoint.GetPrice(),
         Author: bookPoint.Author,
      }})
      if err != nil {
         return err
      }
   }
   return nil
}

客户端实现

func printBookList(ctx context.Context, client book_stream.HelloStreamServiceClient) error {
   req := &book_stream.BookListStreamRequest{}
   listStream, err := client.BookListStream(ctx, req)
   if err != nil {
      return err
   }
   for true {
      resp, err := listStream.Recv()
      if err != nil {
         if err == io.EOF {
            return nil
         }
         return err
      }
      fmt.Printf("%v\n", *resp.Book)
   }
   return nil
}

CreateBookStream

客户端流式 RPC,单向流,客户端通过流式发起多次 RPC 请求给服务端,服务端发起一次响应给客户端

server端实现

func (HelloStreamServiceImpl) CreateBookStream(server book_stream.HelloStreamService_CreateBookStreamServer) error {
   var resList []*book_stream.BookIdPoint
   for {
      resp, err := server.Recv()
      if err == io.EOF {
         return server.SendAndClose(&book_stream.CreateBookStreamResponse{Idx: resList})
      }
      if err != nil {
         return err
      }
      bookStore[resp.Book.Idx] = *resp.Book
      resList = append(resList, &book_stream.BookIdPoint{Idx: resp.Book.Idx})
   }
}

客户端实现

var newBookStore = map[uint64]book_stream.BookPoint{
   3: {
      Idx:    3,
      Author: "程子1",
      Price:  9.9,
      Name:   "游戏思维1",
   },
   4: {
      Idx:    4,
      Author: "丁锐1",
      Price:  9.9,
      Name:   "活出必要的锋芒1",
   },
}

func createBookStream(ctx context.Context, client book_stream.HelloStreamServiceClient) error {
   stream, err := client.CreateBookStream(ctx)
   if err != nil {
      return err
   }
   for _, bookPoint := range newBookStore {
      if err := stream.Send(&book_stream.CreateBookStreamRequest{
         Book: &bookPoint,
      }); err != nil {
         return err
      }
   }
   recv, err := stream.CloseAndRecv()
   if err != nil {
      return err
   }
   fmt.Println(recv.Idx)
   return nil
}

stream.SendAndClose,它是做什么用的呢?

在这段程序中,我们对每一个 Recv 都进行了处理,当发现 io.EOF (流关闭) 后,需要将最终的响应结果发送给客户端,同时关闭正在另外一侧等待的 Recv

stream.CloseAndRecv 和 stream.SendAndClose 是配套使用的流方法,

FindBookByIdStream

服务端实现

func (HelloStreamServiceImpl) FindBookByIdStream(streamServer book_stream.HelloStreamService_FindBookByIdStreamServer) error {
   for {
      resp, err := streamServer.Recv()
      if err == io.EOF {
         return nil
      }
      if err != nil {
         return err
      }
      if book, ok := bookStore[resp.Idx.Idx]; ok {
         if err := streamServer.Send(&book_stream.FindBookByIdStreamResponse{Book: &book}); err != nil {
            return err
         }
      }
   }
}

客户端实现

func getBookListById(ctx context.Context, client book_stream.HelloStreamServiceClient) error {
   stream, err := client.FindBookByIdStream(ctx)
   if err != nil {
      return err
   }
   var findList = []uint64{1, 2}
   for _, idx := range findList {
      err := stream.Send(&book_stream.FindBookByIdStreamRequest{Idx: &book_stream.BookIdPoint{Idx: idx}})
      if err != nil {
         return err
      }
      recv, err := stream.Recv()
      if err != nil {
         return err
      }
      fmt.Printf("%v\n", recv.Book)
   }
   if err := stream.CloseSend(); err != nil {
      return err
   }
   return nil
}

到此这篇关于Go语言Grpc Stream的实现的文章就介绍到这了,更多相关Go语言Grpc Stream 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: Go语言Grpc Stream的实现

本文链接: https://lsjlt.com/news/151958.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Go语言Grpc Stream的实现
    目录Stream GrpcStream Grpc演示BookListStreamCreateBookStreamFindBookByIdStreamStream Grpc 在我们单次...
    99+
    2024-04-02
  • Golang语言实现gRPC的具体使用
    目录gRPC 的特点使用 gRPC 定义服务端使用 gRPC 的客户端gRPC 是通信协议基于 HTTP/2,支持多语言的 RPC 框架,使用 Protobuf 作为它的接口设计语言...
    99+
    2024-04-02
  • Go语言程序开发gRPC服务
    目录前言介绍入门protoserverclient流方式protoserverclient验证器protoToken 认证认证函数:拦截器:初始化:实现接口:连接:单向证书认证生成证...
    99+
    2024-04-02
  • grpc是不是只支持go语言
    这篇文章主要介绍“grpc是不是只支持go语言”,在日常操作中,相信很多人在grpc是不是只支持go语言问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”grpc是不是只支持go语言”的疑惑有所帮助!接下来,请跟...
    99+
    2023-07-04
  • GRPC 是否更倾向于 Go 语言?
    来到编程网的大家,相信都是编程学习爱好者,希望在这里学习Golang相关编程知识。下面本篇文章就来带大家聊聊《GRPC 是否更倾向于 Go 语言?》,介绍一下,希望对大家的知识积累有所帮助,助力实战...
    99+
    2024-04-04
  • 怎么用Python语言的grpc实现消息传送
    这篇“怎么用Python语言的grpc实现消息传送”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么用Python语言的gr...
    99+
    2023-07-05
  • Go语言实现的语言有哪些
    这篇文章主要讲解了“Go语言实现的语言有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Go语言实现的语言有哪些”吧!01 Go+这是国内七牛老大许式伟主导的,对 Go 语言的扩展,专为数...
    99+
    2023-06-15
  • 解密:GRPC 为何选择支持 Go 语言?
    GRPC 是一种跨语言的高性能远程过程调用(RPC)框架,它基于 Protocol Buffers 进行数据传输,提供了强大的功能和性能优势。为了支持不同的编程语言,GRPC 提供了多...
    99+
    2024-04-02
  • 为什么选择 Go 语言来支持 GRPC?
    积累知识,胜过积蓄金银!毕竟在Golang开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《为什么选择 Go 语言来支持 GR...
    99+
    2024-04-04
  • Go gRPC怎么实现Simple RPC
    本篇内容介绍了“Go gRPC怎么实现Simple RPC”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!前言gRPC主要...
    99+
    2023-07-02
  • Go gRPC教程实现Simple RPC
    目录前言新建proto文件创建Server端创建Client端总结前言 gRPC主要有4种请求和响应模式,分别是简单模式(Simple RPC)、服务端流式(Server-side ...
    99+
    2024-04-02
  • GRPC 支持 Go 语言的原因及优势分析
    GRPC 是 Google 开发的一种高性能、跨平台的远程过程调用(RPC)框架,它基于 HTTP/2 和 Protocol Buffers(Protobuf) 进行设计,支持多种语言...
    99+
    2024-04-02
  • GRPC 是否只支持 Go 语言?探究与解析
    GRPC 是否只支持 Go 语言?探究与解析 GRPC(gRPC Remote Procedure Call)是一种高性能、跨语言的远程过程调用框架,最初由Google开发,并在开源社...
    99+
    2024-04-02
  • Go语言中的UTF-8实现
    计算机刚诞生的时候,计算机内的字符可以全部由 ASCII 来表示,ASCII 字符的长度是 7 位,可以表示 128 个字符,对于美国等国家来说是够了,但是对于世界上的其他国家...
    99+
    2022-06-07
    GO go语言
  • Go语言状态机的实现
    目录一、状态机二、代码1. database包2. fsm包3. order包4. main包三、个人总结一、状态机 1. 定义 有限状态机(Finite-state machine...
    99+
    2023-03-09
    Go语言状态机
  • go语言实现mqtt协议的实践
    目录一、什么是MQTT二、Go语言MQTT服务器Broker的搭建三、Go客户端访问简单API一、什么是MQTT MQTT(Message Queuing Telemetry Tra...
    99+
    2024-04-02
  • Go语言单向通道的实现
    目录单向通道的声明格式单向通道的使用例子 time包中的单向通道关闭 channelGo语言的类型系统提供了单方向的 channel 类型,顾名思义,单向 channel ...
    99+
    2023-05-14
    Go语言单向通道 Go单行道
  • go语言使用什么实现的
    go语言使用称为Go Runtime的虚拟机实现的。Go语言的虚拟机是由C语言实现的,它负责Go程序的运行和管理,这个虚拟机可以在不同的操作系统上运行,包括Linux、Windows、macOS等,还提供了垃圾回收机制,可以自动管理内存,减...
    99+
    2023-07-10
  • 解读Go语言实现的奥秘
    go语言通过gc编译器编译为可执行文件,编译过程包括解析、ssa转换、优化和代码生成。其并发性基于csp模型,通过goroutine、通道和选择机制实现。垃圾收集器使用标记-清除算法回收...
    99+
    2024-04-03
    编程 go语言
  • go实现grpc四种数据流模式
    目录1. 什么是数据流2. grpc的四种数据流2.1 简单模式2.2 服务端数据流模式2.3 客户端数据流模式2.4 双向数据流3. 上代码3.1 代码目录3.2 编写stream...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作