首页 > 其他分享 >gRPC的四种通信模式

gRPC的四种通信模式

时间:2024-03-18 15:57:04浏览次数:23  
标签:err proto gRPC 通信 RPC 服务端 go 四种 客户端

目录

gRPC的四种通信模式

  • gRPC有四种通信⽅式,分别是:简单 RPC(Unary RPC)、服务端流式 RPC (Server streaming RPC)、客户端流式 RPC (Clientstreaming RPC)、双向流式 RPC(Bi-directional streaming RPC)。它们主要有以下特点:
服务类型 特点
简单 RPC ⼀般的rpc调⽤,传⼊⼀个请求对象,返回⼀个返回对象
服务端流式 RPC 传⼊⼀个请求对象,服务端可以返回多个结果对象
客户端流式 RPC 客户端传⼊多个请求对象,服务端返回⼀个结果对象
双向流式 RPC 结合客户端流式RPC和服务端流式RPC,可以传⼊多个请求对象,返回多个结果对

一、RPC(Unary RPC)

  • 简单rpc 这就是⼀般的rpc调⽤,⼀个请求对象对应⼀个返回对象

  • 客户端发起⼀次请求,服务端响应⼀个数据,即标准RPC通信。

  • 这种模式,⼀个每⼀次都是发起⼀个独⽴的tcp连接,⾛⼀次三次握⼿和四次挥⼿!

  • 这个就是我们基础案例的示例,模式图如下

[image-20220514155737224](http://photo.liuqingzheng.top/20220514-image-20220514155737224 .png)

二、服务端流RPC

  • 服务端流式rpc ⼀个请求对象,服务端可以传回多个结果对象

  • 服务端流 RPC 下,客户端发出⼀个请求,但不会⽴即得到⼀个响应,⽽是在服务端与客户端之间建⽴⼀个单向的流,服务端可以随时向流
    中写⼊多个响应消息,最后主动关闭流,⽽客户端需要监听这个流,不断获取响应直到流关闭
    应⽤场景举例:

    • 典型的例⼦是客户端向服务端发送⼀个股票代码,服务端就把该股票的实时数据源源不断的返回给客户端

[image-20220514155832935](http://photo.liuqingzheng.top/20220514-image-20220514155832935 .png)

三、客户端流RPC

  • 客户端流式rpc 客户端传⼊多个请求对象,服务端返回⼀个响应结果

  • 应用场景如:物联⽹终端向服务器报送数据

[image-20220514155907457](http://photo.liuqingzheng.top/20220514-image-20220514155907457 .png)

四、双向流RPC

  • 双向流式rpc 结合客户端流式rpc和服务端流式rpc,可以传⼊多个对象,返回多个响应对象

  • 应⽤场景:聊天应⽤

[image-20220514194549273](http://photo.liuqingzheng.top/20220514-image-20220514194549273 .png)

五、综合案例

5.1 新建streamdemo.proto

syntax = "proto3";
option go_package = ".;proto";
// 定义一个服务,gRPC自有的,它需要用grpc插件生成,也就是咱们安装的那个插件
service Greeter{
  // 服务端流模式
  rpc GetStream(StreamRequestData) returns(stream StreamResponseData);
  // 客户端流模式
  rpc PutStream(stream StreamRequestData) returns(StreamResponseData);
  // 双向流模式
  rpc AllStream(stream StreamRequestData) returns(stream StreamResponseData);
}

// 类似于go的结构体,可以定义属性
message StreamRequestData {
  string data = 1;
}
// 定义一个响应的类型
message StreamResponseData {
  string data = 1;
}

5.2 执行命令,生成go文件

//protoc --go_out=. --go_opt=paths=source_relative ./streamdemo.proto
//protoc --go-grpc_out=. --go-grpc_opt=require_unimplemented_servers=false --go-grpc_opt=paths=source_relative ./streamdemo.proto

5.3 客户端

package main

import (
	"context"
	"fmt"
	"go_test_learn/grpc_stream/proto"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"sync"
	"time"
)

func main() {
	conn, err := grpc.Dial("127.0.0.1:50052", grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	client := proto.NewGreeterClient(conn)
	// ******服务端流模式示例***start******
	//res,err:=client.GetStream(context.Background(),&proto.StreamRequestData{Data: "开始要时间"})
	//if err!=nil{
	//	panic(err)
	//}
	//for  { // 开启死循环,不停接收数据
	//	r,err:=res.Recv() // 本质就是socket接收数据
	//	if err != nil {
	//		fmt.Println("接收出错")
	//		break
	//	}
	//	fmt.Println(r.Data)
	//}
	// ******服务端流模式示例***end******

	// ******客户端端流模式示例***start******
	//res, err := client.PutStream(context.Background())
	//if err != nil {
	//	fmt.Println(err)
	//	panic(err)
	//}
	//var i = 0
	//for {
	//	res.Send(&proto.StreamRequestData{
	//		Data: fmt.Sprintf("客户端当前时间为:%v", time.Now().Unix()),
	//	})
	//	time.Sleep(time.Second)
	//	i++
	//	if i == 10 {
	//		break
	//	}
	//}
	// ******客户端流模式示例***end******

	// ******双向流模式示例***start******
	req, err := client.AllStream(context.Background())
	wg := sync.WaitGroup{}
	wg.Add(2)

	// 开协程发送数据,发送10次
	go func() {
		for i := 0; i < 10; i++ {
			req.Send(&proto.StreamRequestData{
				Data: "客户端发送的数据",
			})
			time.Sleep(time.Second)
		}
		wg.Done()
	}()
	// 开协程接收数据,接收10次
	go func() {
		for i := 0; i < 10; i++ {
			r,err:=req.Recv()
			if err != nil {
				fmt.Println("出错了")
				return
			}
			fmt.Println(r.Data)

		}
		wg.Done()
	}()
	wg.Wait()
	// ******双向流模式示例***end******

}

5.4 服务端

package main

import (
	"fmt"
	"go_test_learn/grpc_stream/proto"
	"google.golang.org/grpc"
	"net"
	"sync"
	"time"
)

type GreeterServer struct {
}

// 服务端流模式
func (ser *GreeterServer) GetStream(request *proto.StreamRequestData, response proto.Greeter_GetStreamServer) error {
	fmt.Println(request.Data) // 打印了一下从客户端传入的数据
	var i = 0                 // 定义一个数字,就发送10次
	for {                     // 死循环源源不断向客户端发送
		// 以流的方式向客户端发送数据
		response.Send(&proto.StreamResponseData{
			Data: fmt.Sprintf("当前服务器时间为:%v", time.Now().Unix()),
		})
		time.Sleep(time.Second) // 睡1s钟再发
		i++                     //自增1
		if i == 10 {            // i为10的时候结束
			break
		}
	}
	return nil
}

// 客户端流模式
func (ser *GreeterServer) PutStream(request proto.Greeter_PutStreamServer) error {
	for {
		// 不断的接收并打印客户端发送过来的数据
		res, err := request.Recv()
		if err != nil {
			return err
		}
		fmt.Println(res.Data)
	}
	return nil
}

// 双向流模式
func (ser *GreeterServer) AllStream(request proto.Greeter_AllStreamServer) error {
	// 开启两个协程,一个接收数据,一个发送数据
	var wg=sync.WaitGroup{}
	wg.Add(2)
	go func() { // 发送数据
		for {
			err := request.Send(&proto.StreamResponseData{
				Data: "服务端给你的数据",
			})
			if err != nil {
				fmt.Println(err)
				break
			}
			time.Sleep(time.Second) // 睡1s发送一次
		}
		wg.Done()

	}()
	go func() { // 不停接收数据
		for {
			res, err := request.Recv()
			if err != nil {
				fmt.Println(err)
				break
			}
			fmt.Println(res.Data)
		}
		wg.Done()

	}()

	wg.Wait()
	return nil
}

func main() {
	// 创建一个监听tcp,50052端口
	lis, err := net.Listen("tcp", ":50052")
	if err != nil {
		panic(err)
	}
	// new一个grpc的server
	ser := grpc.NewServer()
	// 注册服务
	proto.RegisterGreeterServer(ser, &GreeterServer{})
	// 让grpc对外提供服务
	err = ser.Serve(lis)
	if err != nil {
		panic(err)
	}

}

六、总结

  • gRPC设计为低延迟和⾼吞吐量通信。gRPC⾮常适⽤于效率⾄关重要的轻型微服务。点对点实时通信 - gRPC对双向流媒体提供出⾊
    的⽀持。

  • gRPC服务可以实时推送消息⽽⽆需轮询。多语⾔混合开发环境 - gRPC⼯具⽀持所有流⾏的开发语⾔,使gRPC成为多语⾔开发环境的理想选择。

  • ⽹络受限环境 - 使⽤Protobuf(⼀种轻量级消息格式)序列化gRPC消息。gRPC消息始终⼩于等效的JSON消息

标签:err,proto,gRPC,通信,RPC,服务端,go,四种,客户端
From: https://www.cnblogs.com/Mcoming/p/18080564

相关文章

  • gRPC进阶
    目录一、grpcmetadata机制1.1proto1.2生成go文件1.3服务端1.4客户端二、grpc拦截器interceptor2.1服务端拦截器grpc.UnaryInterceptor(interceptor)2.2客户端拦截器2.3开源拦截器三、通过metadata+拦截器实现认证3.1自定义(1)服务端(2)客户端(3)proto3.2WithPerRPCCredential......
  • gRPC重试与接口幂等性
    目录一、gRPC超时重试1.1客户端1.2服务端1.3proto二、接口幂等性2.1什么是幂等性2.2什么情况下需要幂等2.3如何保证幂等(1)token机制(2)关键点先删除token,还是后删除token(3)token机制缺点(4)乐观锁机制(5)唯一主键(6)防重表(7)唯一ID(8)唯一ID机制一、gRPC超时重试使用开源的;https://g......
  • 2024年智能通信、大数据与软件工程国际会议(ICICBDSE 2024)
    2024年智能通信、大数据与软件工程国际会议(ICICBDSE2024)2024InternationalConferenceonIntelligentCommunication,BigDataandSoftwareEngineering会议简介:在大数据时代背景下,计算机软件技术的开发情况值得关注。特别是在进行通信和传输的过程中,信息通信系统是最......
  • [Java、Android面试]_08_强软弱虚四种引用及应用场景
    本人今年参加了很多面试,也有幸拿到了一些大厂的offer,整理了众多面试资料,后续还会分享众多面试资料。整理成了面试系列,由于时间有限,每天整理一点,后续会陆续分享出来,感兴趣的朋友可关注+收藏文章目录1.强引用(默认的引用形式)2.软引用3.弱引用4.虚引用引用在java中......
  • 采用设备认证、通信安全、系统安全三大机制,全方位为业务出海保驾护航
    中国联通推出了创新的跨境物联网产品解决方案,通过一卡双IMSI技术实现无感知切换,为企业海外业务提供了一站式的管理和快速部署能力。一、一卡双IMSI,实现无感知切换中国联通跨境物联网产品解决方案的核心亮点在于其采用的一卡双IMSI技术。这种技术使得物联网设备在跨国使用时,无需......
  • 除gRPC之外的另一个选择,IceRPC-支持QUIC
    作者引言自从19年开始接触到RPC,当时完全没有相关概念,接触到的都是http,tcp等,当时公司用的是zeroc出品的ice框架,对应rpc非常强大,跨平台,跨语言。可惜的国内并不是主流,主流是gRPC,万物诸途同归,最终的目地是一样的。主要上看谁简单,方便,好理解。就在去年重新出一个新的RPC框架IceRP......
  • QT5.14.2 探秘Qt信号槽奥秘--让对象间通信如虎添翼
    一、前言在当今这个万物互联的时代,对象间通信无疑是编程领域中最为基础也最为重要的问题。作为知名的跨平台开发框架,Qt自然也需要解决这一问题。于是,Qt巧妙地提出了信号与槽(Signals&Slots)这一机制,以观察者模式的思路让对象间通信变得行云流水。那么,Qt信号与槽的本质......
  • C++ Qt开发:QTcpSocket网络通信组件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QTcpSocket组件实现基于TCP的网络通信功能。QTcpSocket和QTcpServer是Qt中用于实现基于T......
  • 15. SPI通信协议
    一、SPI通信协议简介  SPI是SerialPeripheralinterface缩写,顾名思义就是串行外围设备接口。SPI通信协议是Motorola公司首先在其MC68HCXX系列处理器上定义的。SPI接口是一种高速的全双工同步的通信总线。SCK(SerialClock)时钟信号,由主设备产生。MOSI(MasterOut/......
  • Java创建数组、赋值的四种方式,声明+创建+初始化 详解
    @目录一、创建数组的四种方式二、详解三、数组存储的弊端一、创建数组的四种方式以int数据类型为例@TestpublicvoidtestNewArray(){//创建数组//法一int[]arr1=newint[]{1,2,3,4,5};System.out.println(arr1.length+""+arr1[2]);//5......