golang grpc初体验

news2024/12/25 1:30:50

grpc 是一个高性能、开源和通用的 RPC 框架,面向服务端和移动端,基于 HTTP/2 设计。目前支持c、java和go,分别是grpc、grpc-java、grpc-go,目前c版本支持c、c++、node.js、ruby、python、objective-c、php和c#。grpc官网 grpc-go
在这里插入图片描述
ProtoBuf(全称Protocol Buffer)是数据结构序列化和反序列化框架,ProtoBuf是Google推出的一款轻量高效的数据化数据存储格式,性能比json、xml强,ProtoBuf经历了ProtoBuf2和ProtoBuf3,ProtoBuf3比ProtoBuf简化了很多,目前主流的是ProtoBuf3.
优点:
1.性能:压缩性好、序列化和反序列化快(比xml和json快2-100倍)、传输速度快
2.便捷性:使用简单(自动生成序列化和反序列化代码)、维护成本低(只支持proto文件)、向后兼容(不必破坏旧格式)、加密型号
3.跨语言:跨平台、支持各种主流语言
缺点:
1.通用性差:json可以任何语言都支持,但是protobuf需要专门的解析库
2.自解释性差:只有通过proto文件才能了解数据结构
protoBuf安装并配置环境变量官网
1.编辑环境变量文件‌:vim ~/.zshrc
‌2.添加环境变量‌:

export PATH="$PATH:/usr/local/go/src/GolangStudy/protoc-28.2-osx-x86_64/bin"

3.使配置生效‌:保存并关闭编辑器后,在终端中输入source ~/.zshrc
命令,使更改生效。
4.验证

 protoc --version

安装protoBuf的go依赖包

go get github.com/golang/protobuf/protoc-gen-go

helloworld.proto

syntax = "proto3";

// 生成 proto 文件所在包路径
package protos;
// 影响go文件生成位置和包名
option go_package = "GolangStudy/Introduction/grpc/protos";
message HelloRquest{
    string name=1;//1是编号不是值
}

项目目录结构
在这里插入图片描述
转换命令(第一种命令使用grpc,会比第二种多很多)

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld.proto 
protoc --go_out=/usr/local/go/src/GolangStudy/GolangStudy --proto_path=/usr/local/go/src/GolangStudy/GolangStudy/Introduction/grpc/protos --go_opt=module=GolangStudy helloworld.proto

调用并比较跟json格式的区别

package main

import (
	"GolangStudy/Introduction/grpc/protos"
	"encoding/json"
	"fmt"

	"github.com/golang/protobuf/proto"
)

type Hello struct {
	Name string `json:"name"`
}

func main() {
	req := protos.HelloRquest{
		Name: "bobby",
	}
	jsonStruct := Hello{Name: "bobby"}
	jsonRsp, _ := json.Marshal(jsonStruct)
	fmt.Println(len(string(jsonRsp)))
	rsp, _ := proto.Marshal(&req)
	fmt.Println(len(string(rsp)))
}

json长度是15,而protobuf长度是7

grpc四种数据流

简单模式(simple rpc):客户端发起一次请求,服务端响应一个数据
服务端数据流模式(server-side streaming rpc):客户端发起一次请求,服务端返回一段连续的数据流。(客户端向服务端发送一个股票代码,服务端就把该股票的实时数据源源不断的返回给客户端)
客户端数据流模式(client-side streaming rpc):客户端源源不断的项向服务端发送数据流,而在发送结束后,由服务器返回一个响应(物流网终端向服务器报送数据)
双向数据流模式(bidirectional streaming rpc):客户端和服务端都可以向双方发送数据流,双方的数据可以同时互相发送,可以实现实时交互(聊天机器人)

grpc简单模式

目录结构
在这里插入图片描述

proto代码

syntax = "proto3";

// 生成proto文件所在包路径
package protos;
option go_package = ".;proto";
// 影响go文件生成位置和包名
service Greeter{
    rpc SayHello(HelloRquest)returns(HelloReply);//hello接口
}
message HelloRquest{
    string name=1;//1是编号不是值
}
message HelloReply{
    string message=1;
}

生成go文件

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld.proto

使用接口删除这一行(可能是生成方式的问题)
在这里插入图片描述
server端

package main

import (
	"GolangStudy/Introduction/grpc/example2/proto"
	"context"
	"net"

	"google.golang.org/grpc"
)

type Server struct {
}

func (s *Server) SayHello(ctx context.Context, request *proto.HelloRquest) (*proto.HelloReply, error) {
	return &proto.HelloReply{
		Message: "helo" + request.Name,
	}, nil
}
func main() {
	g := grpc.NewServer()
	proto.RegisterGreeterServer(g, &Server{})
	lis, err := net.Listen("tcp", "0.0.0.0:8080")
	if err != nil {
		panic("failed to listen:" + err.Error())
	}
	err = g.Serve(lis)
	if err != nil {
		panic("failed to start ")
	}
}

client端

package main

import (
	"GolangStudy/Introduction/grpc/example2/proto"
	"context"
	"fmt"

	"google.golang.org/grpc"
)

func main() {
	conn, err := grpc.Dial("127.0.0.1:8080", grpc.WithInsecure())
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	c := proto.NewGreeterClient(conn)
	r, err := c.SayHello(context.Background(), &proto.HelloRquest{
		Name: "bobby",
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(r.Message)
}

grpc流模式

proto

syntax = "proto3";

// 生成proto文件所在包路径
package protos;
option go_package = ".;proto";
// 影响go文件生成位置和包名
service Greeter{
    rpc GetStream(StreamReqData)returns(stream SteramResData);//服务端流模式
    rpc PostStream(stream StreamReqData)returns(stream SteramResData);//客户端流模式
    rpc AllStream(stream StreamReqData)returns(stream SteramResData);//双向流模式
}
message StreamReqData{
    string data=1;
}
message SteramResData{
    string data=1;
}

生成go文件

 protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative stream.proto

删除
在这里插入图片描述
server

package main

import (
	"GolangStudy/Introduction/grpc/stream_grpc_test/proto"
	"fmt"
	"net"
	"sync"
	"time"

	"google.golang.org/grpc"
)

const PORT = ":50052"

type server struct {
}

func (s *server) GetStream(req *proto.StreamReqData, res proto.Greeter_GetStreamServer) error {
	i := 0
	for {
		i++
		_ = res.Send(&proto.SteramResData{
			Data: fmt.Sprintf("%v", time.Now().Unix()),
		})
		time.Sleep(time.Second)
		if i > 10 {
			break
		}
	}
	return nil
}
func (s *server) PostStream(cliStr proto.Greeter_PostStreamServer) error {
	for {
		if a, err := cliStr.Recv(); err != nil {
			fmt.Println(err)
			break
		} else {
			fmt.Println(a.Data)
		}
	}
	return nil
}
func (s *server) AllStream(allStr proto.Greeter_AllStreamServer) error {
	wg := sync.WaitGroup{}
	wg.Add(2)
	go func() {
		defer wg.Done()
		for {
			data, _ := allStr.Recv()
			fmt.Println("收到客户端消息:" + data.Data)
		}
	}()
	go func() {
		defer wg.Done()
		for {
			allStr.Send(&proto.SteramResData{
				Data: "我是服务器",
			})
			time.Sleep(time.Second)
		}
	}()
	wg.Wait()
	return nil
}
func main() {
	lis, err := net.Listen("tcp", PORT)
	if err != nil {
		panic(err)
	}
	s := grpc.NewServer()
	proto.RegisterGreeterServer(s, &server{})
	err = s.Serve(lis)
	if err != nil {
		panic("failed to start ")
	}
}

client

package main

import (
	"GolangStudy/Introduction/grpc/stream_grpc_test/proto"
	"context"
	"fmt"
	"sync"
	"time"

	"google.golang.org/grpc"
)

func main() {
	conn, err := grpc.Dial("127.0.0.1:50052", grpc.WithInsecure())
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	//服务端流模式
	// c := proto.NewGreeterClient(conn)
	// res, _ := c.GetStream(context.Background(), &proto.StreamReqData{Data: "mooc"})
	// for {
	// 	a, err := res.Recv() //socket编程send recv
	// 	if err != nil {
	// 		fmt.Println(err)
	// 		break
	// 	}
	// 	fmt.Println(a)

	// }

	// //客户端流模式
	// c := proto.NewGreeterClient(conn)
	// putS, _ := c.PostStream(context.Background())
	// i := 0
	// for {
	// 	i++
	// 	_ = putS.Send(&proto.StreamReqData{
	// 		Data: fmt.Sprintf("mooc%d", i),
	// 	})
	// 	time.Sleep(time.Second)
	// 	if i > 10 {
	// 		break
	// 	}
	// }

	//双向流模式
	c := proto.NewGreeterClient(conn)
	allStr, _ := c.AllStream(context.Background())
	wg := sync.WaitGroup{}
	wg.Add(2)
	go func() {
		defer wg.Done()
		for {
			data, _ := allStr.Recv()
			fmt.Println("收到服务器消息:" + data.Data)
		}
	}()
	go func() {
		defer wg.Done()
		for {
			allStr.Send(&proto.StreamReqData{
				Data: "我是客户端",
			})
			time.Sleep(time.Second)
		}
	}()
	wg.Wait()
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2186113.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux相关概念和重要知识点(11)(进程调度、Linux内核链表)

1.Linux调度算法 上篇文章我粗略讲过queue[140]的结构,根据哈希表,我们可以将40个不同优先级的进程借助哈希桶链入queue[140]中。调度器会根据queue的下标来进行调度。但这个具体的调度过程是怎样的呢?以及runqueue和queue[140]的关系是什么…

谷歌给到的185个使用生成式AI的案例

很多公司从利用AI回答问题,进而使用AI进行预测,向使用生成式AI Agent转变。AI Agent的独特之处在于它们可以采取行动以实现特定目标,比如引导购物者找到合适的鞋子,帮助员工寻找合适的健康福利,或在护理人员交接班期间…

python之输入输出

1、输入 Python在控制台输入内容,需要使用input函数。input函数会在控制台等待用户输入,直到用户按下了回车键才算完成输入。 注意:input函数接收的内容为字符串。 str1 input("请输入内容\n") print(str1) print(type(str1))1…

Python酷库之旅-第三方库Pandas(132)

目录 一、用法精讲 591、pandas.DataFrame.plot方法 591-1、语法 591-2、参数 591-3、功能 591-4、返回值 591-5、说明 591-6、用法 591-6-1、数据准备 591-6-2、代码示例 591-6-3、结果输出 592、pandas.DataFrame.plot.area方法 592-1、语法 592-2、参数 592-…

9.28学习笔记

1.ping 网址 2.ssh nscc/l20 3.crtl,打开vscode的setting 4.win 10修改ssh配置文件及其密钥权限为600 - 晴云孤魂 - 博客园 整体来看: 使用transformer作为其主干网络,代替了原先的UNet 在latent space进行训练,通过transformer处理潜…

查缺补漏----该不该考虑不可屏蔽中断

可以看看这个视频: 讨论中断时,该不该考虑不可屏蔽中断?_哔哩哔哩_bilibili 首先要知道一个概念:可屏蔽中断和不可屏蔽中断 可屏蔽中断: 可屏蔽中断是可通过中断屏蔽字来启用或禁用的中断。对于多级中断而言&#…

①EtherCAT转ModbusTCP, EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关

EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关https://item.taobao.com/item.htm?ftt&id822721028899 协议转换通信网关 EtherCAT 转 ModbusTCP GW系列型号 MS-GW15 简介 MS-GW15 是 EtherCAT 和 Modbus TCP 协议转换网关,为用户提供一种 …

map_set的使用

map_set的使用 关联式容器树形结构的关联式容器setset的介绍set的使用 multisetmultiset的介绍multiset的使用 mapmap的介绍map的使用键值对 multimapmultimap的介绍 🌏个人博客主页:个人主页 关联式容器 在初阶阶段,我们已经接触过STL中的部…

黑科技外绘神器:一键扩展图像边界

黑科技外绘神器:一键扩展图像边界 Diffusers Image Outpaint✨是一个开源工具,能智能扩展图像边界,创造完美视觉效果🏞️。用户可自定义风格,生成高清图像🤩,应用场景广泛,释放你的…

大模型~合集6

我自己的原文哦~ https://blog.51cto.com/whaosoft/11566566 # 深度模型融合(LLM/基础模型/联邦学习/微调等) 23年9月国防科大、京东和北理工的论文“Deep Model Fusion: A Survey”。 深度模型融合/合并是一种新兴技术,它将多个深度学习模…

爬虫——爬取小音乐网站

爬虫有几部分功能??? 1.发请求,获得网页源码 #1.和2是在一步的 发请求成功了之后就能直接获得网页源码 2.解析我们想要的数据 3.按照需求保存 注意:开始爬虫前,需要给其封装 headers {User-…

本地化测试对游戏漏洞修复的影响

本地化测试在游戏开发的质量保证过程中起着至关重要的作用,尤其是在修复bug方面。当游戏为全球市场做准备时,它们通常会被翻译和改编成各种语言和文化背景。这种本地化带来了新的挑战,例如潜在的语言错误、文化误解,甚至是不同地区…

C++ 双端队列(deque)的深入理解

前言: 双端队列deque看起来是一个相当牛的容器,表面看起来将list和vector进行结合起来,形成了一个看起来很完美的容器,但是事实不是这样,要是deque如此完美,数据结构也就没list和vector的事情了&#xff0c…

多系统萎缩患者必看!这些维生素助你对抗病魔

亲爱的朋友们,今天我们来聊聊一个相对陌生但重要的健康话题——多系统萎缩(MSA)。这是一种罕见的神经系统疾病,影响着患者的自主神经系统、运动系统和平衡功能。面对这样的挑战,科学合理的饮食和营养补充显得尤为重要。…

暴力数据结构——AVL树

1.认识AVL树 AVL树最先发明的⾃平衡⼆叉查找树,AVL可以是⼀颗空树,或者具备下列性质的⼆叉搜索树: • 它的左右⼦树都是AV树,且左右⼦树的⾼度差的绝对值不超过1 • AVL树是⼀颗⾼度平衡搜索⼆叉树, 通过控制⾼度差去控制平衡 AVL树整体结点…

路由交换实验指南

案例 01:部署使用 eNSP 平台实验需求: 安装华为 eNSP 网络模拟平台打开 eNSP 平台,新建拓扑并绘制网络能够成功启动交换机、计算机设备 实验步骤: 安装华为 eNSP 网络模拟平台启动安装程序 配置安装内容 防护墙允许 eNSP 程序的…

IDTL:茶叶病害识别数据集(猫脸码客 第205期)

Identifying Disease in Tea Leaves茶叶病害识别数据集 一、引言 在农业领域,茶叶作为一种重要的经济作物,其生产过程中的病害防治是确保茶叶质量和产量的关键环节。然而,传统的病害识别方法主要依赖于人工观察和经验判断,这不仅…

从零开始实现RPC框架---------项目介绍及环境准备

一,介绍 RPC(Remote Procedure Call)远程过程调⽤,是⼀种通过⽹络从远程计算机上请求服务,⽽不需要 了解底层⽹络通信细节。RPC可以使⽤多种⽹络协议进⾏通信, 如HTTP、TCP、UDP等, 并且在 TCP/…

匿名方法与Lambda表达式+泛型委托

匿名方法 和委托搭配使用,方便我们快速对委托进行传参,不需要我们定义一个新的函数,直接用delegate关键字代替方法名,后面跟上参数列表与方法体。 格式:delegate(参数列表){方法体} lambda表达式 是匿名方法的升级…

Brave编译指南2024 MacOS篇-环境配置(四)

引言 在上一篇文章中,我们成功获取了Brave浏览器的源代码。现在,我们将进入编译过程的关键阶段:环境配置。正确的环境配置对于成功编译Brave浏览器至关重要,它能确保所有必要的工具和依赖项都已就位,并且版本兼容。 …