1. 什么是数据流

  grpc中的stream,srteam顾名思义就是一种流,可以源源不断的推送数据,很适合传输一些大数据,或者服务端和客户端长时间数据交互,比如客户端可以向服务端订阅一个数据,服务端就可以利用stream,源源不断地推送数据。

底层还原成socket编程

2. grpc的四种数据流

1.简单模式
2.服务端数据流模式(Server-side streaming RPC)
3.客户端数据流模式(Client-side streaming RPC)
4.双向数据流模式(Bidirectional streaming RPC)

2.1 简单模式

  这种模式最为传统,即客户端发起一次请求,服务端响应一个数据,这和大家平时熟悉的RPC没有什么大的区别,上两篇中介绍此模式。

2.2 服务端数据流模式

  这种模式是客户端发起一次请求,服务端返回一段连续的数据流。典型的例子是客户端向服务端发送一个股票代码,服务端就把该股票的实时数据源源不断的返回给客户端

2.3 客户端数据流模式

  与服务端数据流模式相反,这次是客户端源源不断的向服务端发送数据流,而在发送结束后,由服务端返回一个响应。典型的例子是物联网终端向服务器报送数据。

2.4 双向数据流

  顾名思义,这是客户端和服务端都可以向对方发送数据流,这个时候双方的数据可以同时互相发送,也就是可以实现实时交互。典型的例子是聊天机器人。

3. 上代码

3.1 代码目录

3.2 编写stream.proto文件

stream是常量,写在哪一边,哪一边就是数据流
syntax = "proto3";

option go_package = "./;proto";

service Greeter {
// 定义方法,stream是常量,流模式
rpc ServerStream (StreamRequestData) returns (stream StreamResponseData); //服务端流模式,拉消息
rpc ClientStream (stream StreamRequestData) returns (StreamResponseData); //客户端流模式,推消息
rpc AllStream (stream StreamRequestData) returns (stream StreamResponseData); //双向流模式,能推能拉
} message StreamRequestData {
string data = 1; //编号
} message StreamResponseData {
string data = 1; //编号
}
生成go的protobuf文件命令:
cd到proto目录下
命令:protoc -I . hello.proto --go_out=plugins=grpc:.

3.3 编写server文件

package main

import (
"file_test/grpc_go_stream/proto"
"fmt"
"net"
"sync"
"time" "google.golang.org/grpc"
) const port = 8082 type server struct{} func (s *server) ServerStream(req *proto.StreamRequestData, res proto.Greeter_ServerStreamServer) error {
i := 0
for {
i++
//业务代码
_ = res.Send(&proto.StreamResponseData{
Data: fmt.Sprintf("这是发给%s的数据流", req.Data),
})
time.Sleep(time.Second * 1)
if i > 10 {
break
}
}
return nil
}
func (s *server) ClientStream(cliStr proto.Greeter_ClientStreamServer) error {
for {
//业务代码
res, err := cliStr.Recv()
if err != nil {
fmt.Println("本次客户端流数据发送完了:",err)
break
}
fmt.Println("客户端发来消息:",res.Data)
}
return nil
}
func (s *server) AllStream(allStr proto.Greeter_AllStreamServer) error {
wg:=sync.WaitGroup{}
wg.Add(2)
//接受客户端消息的协程
go func() {
defer wg.Done()
for {
//业务代码
res, err := allStr.Recv()
if err != nil {
fmt.Println("本次客户端流数据发送完了:",err)
break
}
fmt.Println("收到客户端发来消息:",res.Data)
}
}() //发送消息给客户端的协程
go func() {
defer wg.Done()
i := 0
for {
i++
//业务代码
_ = allStr.Send(&proto.StreamResponseData{
Data: fmt.Sprintf("这是发给客户端的数据流"),
})
time.Sleep(time.Second * 1)
if i > 10 {
break
}
}
}()
wg.Wait()
return nil
} // 启动
func start() {
// 1.实例化server
g := grpc.NewServer()
// 2.注册逻辑到server中
proto.RegisterGreeterServer(g, &server{})
// 3.启动server
lis, err := net.Listen("tcp", "127.0.0.1:8082")
if err != nil {
panic("监听错误:" + err.Error())
}
err = g.Serve(lis)
if err != nil {
panic("启动错误:" + err.Error())
} } func main() {
start()
}

3.4 编写client文件

package main

import (
"context"
"file_test/grpc_go_stream/proto"
"fmt"
"sync"
"time" "google.golang.org/grpc"
) var rpc proto.GreeterClient func serverStreamDemo() {
//服务端流模式
res,err:=rpc.ServerStream(context.Background(),&proto.StreamRequestData{Data: "jeff"})
if err != nil {
panic("rpc请求错误:"+err.Error())
}
for {
data,err:=res.Recv() //
if err != nil {
fmt.Println("客户端发送完了:",err)
return
}
fmt.Println("客户端返回数据流值:",data.Data)
}
} func clientStreamDemo() {
//客户端流模式
cliStr, err := rpc.ClientStream(context.Background())
if err != nil {
panic("rpc请求错误:" + err.Error())
}
i := 0
for {
i++
_ = cliStr.Send(&proto.StreamRequestData{
Data: "jeff",
})
time.Sleep(time.Second * 1)
if i > 10 {
break
}
}
} func clientAndServerStreamDemo() {
//双向流模式
allStr, _ := rpc.AllStream(context.Background())
wg := sync.WaitGroup{}
wg.Add(1)
//接受服务端消息的协程
go func() {
defer wg.Done()
for {
//业务代码
res, err := allStr.Recv()
if err != nil {
fmt.Println("本次服务端流数据发送完了:", err)
break
}
fmt.Println("收到服务端发来消息:", res.Data)
}
}() //发送消息给服务端的协程
go func() {
defer wg.Done()
i := 0
for {
i++
//业务代码
_ = allStr.Send(&proto.StreamRequestData{
Data: fmt.Sprintf("这是发给服务端的数据流"),
})
time.Sleep(time.Second * 1)
if i > 10 {
break
}
}
}()
wg.Wait()
} // 启动
func start() {
conn, err := grpc.Dial("127.0.0.1:8082", grpc.WithInsecure())
if err != nil {
panic("rpc连接错误:" + err.Error())
}
defer conn.Close()
rpc = proto.NewGreeterClient(conn) //初始化 serverStreamDemo() //服务端流模式 clientStreamDemo() //客户端流模式 clientAndServerStreamDemo() // 双向流模式
} func main() {
start()
}

grpc流模式-go实现的更多相关文章

  1. TCP的流模式与UDP的报文模式对比

    1       案例背景 在学习TCP-IP协议详解卷一时,读到介绍TCP协议的部分,发现TCP的首部是没有报文总长度字段的,而在UDP中是有的,对这个问题的思考引出了两者之间的区别. 2    案例 ...

  2. TCP 流模式与UDP数据报模式(转)

    TCP流模式与UDP数据报模式http://blog.csdn.net/s3olo/article/details/7914717 数据报(datagram)通常是指起始点和目的地都使用无连接网络服务 ...

  3. RecyclerView实例-实现可下拉刷新上拉加载更多并可切换线性流和瀑布流模式(1)

    摘要 最近项目有个列表页需要实现线性列表和瀑布流展示的切换,首先我想到的就是上 [RecyclerView],他本身已经很好的提供了三种布局方式,只是简单做个切换应该是很简单的事情,如果要用Recyc ...

  4. kcp流模式与消息模式对比

    kcp的流模式,和消息模式 流模式: 更高的网络利用率 更大的传输速度 解析数据相对更复杂 消息模式: 更小的网络利用率 更小的传输速度 解析数据相对更简单 消息模式的示意图 http://www.p ...

  5. grpc Unary模式下客户端创建insecure channel的主要流程

    (原创)C/C/1.25.0-dev grpc-c/8.0.0, 使用的例子是自带的例子GreeterClient grpc Unary模式下客户端创建insecure channel的主要流程 gr ...

  6. WAFの基本防护透明流模式v1.0

                      一.WAFの透明流模式     1)首先先配置WAF的网络,配置一个网桥接口,设置IP便于带内管理.             2)当然,如果需要不同网段之间都能够管 ...

  7. 流量治理神器-Sentinel的限流模式,选单机还是集群?

    大家好,架构摆渡人.这是我的第5篇原创文章,还请多多支持. 上篇文章给大家推荐了一些限流的框架,如果说硬要我推荐一款,我会推荐Sentinel,Sentinel的限流模式分为两种,分别是单机模式和集群 ...

  8. 容量测试之tcpcopy引流模式

    tcpcopy 给用户提供了很多命令参数来修改引流的模式和设置,详细可以查阅手册.在这里把几种常见的引流方式做个归纳小结,以tcpcopy传统架构使用命令举例. 1.分布式引流 用法:Tcpcopy可 ...

  9. IE文档版本和文档流模式

    使用X-UA-Compatible来设置IE浏览器兼容模式 文件兼容性用于定义让IE如何编译你的网页.此文件解释文件兼容性,如何指定你网站的文件兼容性模式以及如何判断一个网页该使用的文件模式. < ...

随机推荐

  1. 嵌入式Linux应用开发完全手册之环境搭建

    @ 目录 0.下载源配置 1.电脑BIOS启动虚拟化 2.linux网卡查看与IP设置 3.windows NAT虚拟网络配置 4.修改 Ubuntu 的 mountd 端口 5.vim设置 6.Mo ...

  2. ShardingSphere-Proxy(一)

    1.现实中的问题 我们知道数据库的数据,基本80%的业务是查询,20%的业务涵盖了增删改,经过长期的业务变更和积累数据库的数据到达了一定的数量之后,直接影响的是用户与系统的交互,查询时的速度,插入数据 ...

  3. Jenkins+Docker+Git 自动化部署

    Jenkins+Docker+Git 自动化部署图文教程 https://blog.csdn.net/qq_38252039/article/details/89791247 前言: 通过几天的学习和 ...

  4. kafka中的broker 是干什么的?

     broker 是消息的代理,Producers往Brokers里面的指定Topic中写消息,Consumers从Brokers里面拉取指定Topic的消息,然后进行业务处理,broker在中间起到一 ...

  5. swagger-ui提交请求无name(指input中的name属性)值

    swagger-ui提交请求,请求不包含name值,造成后台无法进行接受参数. @Operation(description = "上传文件",tags = "上传&qu ...

  6. Redis 支持的 Java 客户端都有哪些?官方推荐用哪个?

    Redisson.Jedis.lettuce 等等,官方推荐使用 Redisson.

  7. vue 3d轮播组件 vue-carousel-3d

    开发可视化项目时,需要3d轮播图,找来找去发现这个组件,引用简单,最后实现效果还不错.发现关于这个组件,能搜到的教程不多,就分享一下我的经验. 插件github地址:https://wlada.git ...

  8. 探索前端黑科技——通过 png 图的 rgba 值缓存数据

    本文系原创,欢迎转载,转载请注明作者信息项目地址:SphinxJS在线体验地址:https://jrainlau.github.io/sp... 说起前端缓存,大部分人想到的无非是几个常规的方案,比如 ...

  9. HTML+CSS基础课程-imooc-【更新完毕】

    6-1 认识CSS样式 CSS全称为"层叠样式表 (Cascading Style Sheets)",它主要是用于定义HTML内容在浏览器内的显示样式,如文字大小.颜色.字体加粗等 ...

  10. CSS3 用border写 空心三角箭头 (两种写法)

    之前一直在寻找这种空心三角箭头, 终于知道了原理! 自己记录一下,顺便分享给之前跟我一样想要的撸友们~ 第一种写法 利用常见的 after伪元素 <!DOCTYPE html> <h ...