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. python单ip端口扫描器

    from socket import * import threading #导入线程相关模块 # qianxiao996精心制作 #博客地址:https://blog.csdn.net/qq_363 ...

  2. 查找goog13的ip

    C:\Users\Deen>ping 172.217.24.14 Pinging 172.217.24.14 with 32 bytes of data: Reply from 172.217. ...

  3. length()与trim()函数用法

    student表 SELECT * from `student` where length(sex) = 0 SELECT length(ID) from `student` WHERE provin ...

  4. Apache+tomcat实现应用服务器集群

    Ngnix/Apache比较 Nginx:Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行.其特点是占有内存少,并发能力 ...

  5. git 的使用(新手)

    git的使用心得 windows版本下载git地址 git config --global user.name 用户名 在使用git前要注册用户名(个人称谓) git config --global ...

  6. 文字图片在wps中清晰化方法

    在wps中双击图片出属性,然后再选择文字增强.选择对比增加即可.

  7. Homebrew安装环境

    p.p1 { margin: 0; font: 11px Menlo; color: rgba(0, 0, 0, 1) } span.s1 { font-variant-ligatures: no-c ...

  8. 面试问题之C++语言:说一说C++中四种cast转换

    C++中四种类型转换是:static_cast.dynamic_cast.const_cast.reinterpret_cast 1.const_cast 常量转换,用于将const变量转为非cons ...

  9. Zookeeper 下 Server 工作状态?

    服务器具有四种状态,分别是 LOOKING.FOLLOWING.LEADING.OBSERVING. 1.LOOKING:寻找 Leader 状态.当服务器处于该状态时,它会认为当前集群中没有 Lea ...

  10. 【freertos】007-系统节拍和系统延时管理实现细节

    前言 本章节的时钟系统节拍主要分析FreeRTOS内核相关及北向接口层,南向接口层不分析. 本章节的系统延时主要分析任务系统延时实现. 原文:李柱明博客:https://www.cnblogs.com ...