远程过程调用协议gRPC及在go环境下的使用

1. 远程过程调用协议

1.1 定义

  远程过程调用(Remote Procedure Call,PRC是一种进程间通信技术,它使得程序可以像调用本地函数一样调用远程服务器上的函数。RPC 屏蔽了底层的通信细节,让开发者能够更专注于业务逻辑,而无需关心网络编程的复杂性。其流程如下:
在这里插入图片描述

1.2 grpc

  gRPC是由 Google 开发的一个高性能、开源的 RPC 框架,基于 HTTP/2 协议并使用Protocol Buffers(protobuf)作为接口描述语言。

2. Protocol Buffers

  Protocol Buffers(Protobuf)是由Google开发的一种语言中立、平台中立、可扩展的序列化数据格式。它用于在不同的程序和系统之间进行高效的数据交换。Protobuf 允许开发者定义数据结构(消息)并自动生成代码来处理这些数据结构的序列化和反序列化。Protocol Buffers具有以下优点:

  • 高效性:Protobuf 使用紧凑的二进制格式,比传统的文本格式(如 XML 或 JSON)更节省空间和带宽,序列化和反序列化速度快,适合高性能需求的场景。
  • 跨语言支持:Protobuf 支持多种编程语言,包括但不限于 C++, Java, Python, Go, C#, Ruby, JavaScript 等。这种跨语言特性使得它在异构系统中非常有用。
  • 可扩展性:Protobuf 允许数据结构的灵活扩展,新的字段可以添加而不会破坏已有的数据格式。这种向后兼容性使得在系统升级和维护过程中更容易处理。
  • 自动生成代码:开发者定义数据结构的.proto文件后,可以使用 protoc 编译器生成目标语言的代码,减少手工编码的错误和工作量。
2.1 基础语法

  Protobuf的定义文件.proto一般包含语法版本声明、包声明、消息定义和服务定义四个部分。其基本结构如下:

syntax = "proto3";
option go_package="./project/generated"
package example;
message MessageName {//定义消息// 字段定义
}
service Greeter { //定义服务
}
  • 语法版本声明:使用syntax指定.proto文件的语法版本,一般常用的语法版本有:proto2proto3
  • 包声明:package关键字用于指定代码的命名空间。
  • optiongo_pacakge指定了生成的Go代码应该放置的路径名。go_package中至少要包含一个/.
  • 消息定义:使用message关键字声明消息类型。消息类型中存放数据结构。一个消息类型包含一个或多个字段,每个字段有一个唯一的编号。举例如下:
message Person {string name = 1;   // 类型、字段名及其唯一编号。int32 id = 2;string email = 3;
}
  • 服务定义:使用service关键字声明服务类型,服务用于定义 RPC 服务接口。举例如下:
service Greeter {rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {string name = 1;
}
message HelloReply {string message = 1;
}

3. go环境下的grpc案例

3.1 安装相关的包

先在go语言的project中安装grpc相关的包,具体命令如下

go get google.golang.org/grpc
go get google.golang.org/protobuf
go get google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
go get google.golang.org/protobuf/cmd/protoc-gen-go@latest
3.2 编写helloworld.proto文件

如果go环境使用的是GoLand等,需要先安装protobuf插件。具体过程这里不在赘述。

syntax = "proto3";
option go_package="./generated";
package helloworld;
service Greeter {rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {string name = 1;
}
message HelloReply {string message = 1;
}

接着使用protoc命令将helloworld.proto文件编译成go语言的源代码。具体命令如下:

 protoc --go_out=. --go-grpc_out=. helloworld.proto

其中:
--go_out指定生成Go代码的输出目录。
--go-grpc_out指定生成Go gRPC代码的输出目录。

3.3 客户端/服务端代码

服务端代码server.go

package main
import ("context""google.golang.org/grpc"pb "grpc_test/proto/generated" //引用protoc生成的go package"log""net"
)
type server struct {pb.UnimplementedGreeterServer
}
//实现sayhello函数
func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {return &pb.HelloReply{Message: "Hello, " + req.Name}, nil
}
func main() {lis, err := net.Listen("tcp", ":50051")if err != nil {log.Fatalf("failed to listen: %v", err)}s := grpc.NewServer()pb.RegisterGreeterServer(s, &server{})if err := s.Serve(lis); err != nil {log.Fatalf("failed to serve: %v", err)}
}

客户端代码client.go

package main
import ("context""flag""log""time""google.golang.org/grpc""google.golang.org/grpc/credentials/insecure"pb "grpc_test/proto/generated"
)
const (defaultName = "world"
)
var (addr = flag.String("addr", "localhost:50051", "the address to connect to")name = flag.String("name", defaultName, "Name to greet")
)
func main() {flag.Parse()// Set up a connection to the server.conn, err := grpc.NewClient(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))if err != nil {log.Fatalf("did not connect: %v", err)}defer conn.Close()c := pb.NewGreeterClient(conn)// Contact the server and print out its response.ctx, cancel := context.WithTimeout(context.Background(), time.Second)defer cancel()r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})if err != nil {log.Fatalf("could not greet: %v", err)}log.Printf("Greeting: %s", r.GetMessage())
}

这里完整的代码结构如下:
在这里插入图片描述
然后分别server.goclient.go文件(如果是在GoLand中,这两个文件要分别运行在两个终端中),可以看到如下结果:

2024/06/25 20:51:17 Greeting: Hello, world

参考资料

  1. https://blog.csdn.net/m0_68949064/article/details/123974867

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

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

相关文章

无源电压继电器 JDY-1210AW 导轨安装 约瑟JOSEF

系列型号: JDY-1002AW电压继电器;JDY-1002B电压继电器; JDY-1110AW电压继电器;JDY-1110B电压继电器; JDY-1220AW电压继电器;JDY-1220B电压继电器; JDY-1100AW电压继电器;JDY-110…

服务器数据恢复—用raid6阵列磁盘组建raid5阵列如何恢复原raid数据?

服务器存储数据恢复环境: 华为OceanStor 5800存储,该存储中有一组由10块硬盘组建的raid6磁盘阵列,供企业内部使用,服务器安装linux操作系统EXT3文件系统,划分2个lun。 服务器存储故障: 管理员发现存储中rai…

JavaScript的学习之dom的查询(一)

一、获得元素 通过document对象调用&#xff1a; getElementById()&#xff1a;通过id属性获取一个元素节点对象getElementsByTagName()&#xff1a;通过标签名获取一组元素节点对象getElementsByName()&#xff1a;通过name属性来获取一组元素节点对象 核心学习代码 <scrip…

记录一次即将出现的钓鱼新方式

钓鱼通常是内网渗透过程中的最为常见的入口方式&#xff0c;但是随着蓝队人员溯源反制思路开阔&#xff0c;入侵排查能力提升&#xff0c;钓鱼也越来越困难&#xff0c;这里就记一种不同寻常的钓鱼方式。 pip install 的执行流程&#xff1a; 先获取到远端的服务器地址 url 比…

单目标应用:基于吸血水蛭优化器(Blood-Sucking Leech Optimizer,BSLO)的微电网优化(MATLAB代码)

一、微电网模型介绍 微电网多目标优化调度模型简介_vmgpqv-CSDN博客 参考文献&#xff1a; [1]李兴莘,张靖,何宇,等.基于改进粒子群算法的微电网多目标优化调度[J].电力科学与工程, 2021, 37(3):7 二、吸血水蛭优化器求解微电网 2.1算法简介 吸血水蛭优化器&#xff08;B…

【Java Web】Tomcat服务器

目录 一、Tomcat是什么 二、Tomcat安装 三、Tomcat相关目录 四、Web项目标准目录结构规范 五、Tomcat项目部署方式 六、IDEA关联本地Tomcat 七、HTTP协议 7.1 http的交互方式 7.1.1 http长连接和短连接 7.1.2 http1.1缓存机制 7.2 http数据报文格式 八、常见响应状态码 一、Tom…

印刷企业数字工厂管理系统如何保障产品质量

一、引言 随着信息技术的迅猛发展&#xff0c;印刷行业也迎来了数字化转型的浪潮。数字工厂管理系统作为这一转型的核心工具&#xff0c;不仅在提高生产效率、优化资源配置方面发挥了重要作用&#xff0c;更在保障产品质量上扮演着关键角色。本文将深入探讨印刷企业数字工厂管…

浏览器扩展V3开发系列之 chrome.contextMenus 右键菜单的用法和案例

【作者主页】&#xff1a;小鱼神1024 【擅长领域】&#xff1a;JS逆向、小程序逆向、AST还原、验证码突防、Python开发、浏览器插件开发、React前端开发、NestJS后端开发等等 chrome.contextMenus 允许开发者向浏览器的右键菜单添加自定义项。 在使用 chrome.contextMenus 之前…

本地读取classNames txt文件

通过本地读取classNames,来减少程序修改代码,提高了程序的拓展性和自定义化。 步骤: 1、输入本地路径,分割字符串。 2、将className按顺序放入vector容器中。 3、将vector赋值给classNmaes;获取classNames.size(),赋值给CLASSES;这样,类别个数和类别都已经赋值完成。…

Python | Leetcode Python题解之第199题二叉树的右视图

题目&#xff1a; 题解&#xff1a; class Solution:def rightSideView(self, root: TreeNode) -> List[int]:rightmost_value_at_depth dict() # 深度为索引&#xff0c;存放节点的值max_depth -1stack [(root, 0)]while stack:node, depth stack.pop()if node is not…

第N8周:seq2seq翻译实战-Pytorch复现

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 一、前期准备 from __future__ import unicode_literals, print_function, division from io import open import unicodedata import s…

50、基于NARX神经网络的磁悬浮建模(matlab)

1、NARX神经网络简介 NARX&#xff08;非线性自回归外部输入&#xff09;神经网络是一种用于非线性建模和预测的神经网络结构。与传统的自回归模型不同&#xff0c;NARX网络可以接收外部输入来影响输出结果&#xff0c;从而更好地捕捉系统的复杂性和非线性特征。 NARX神经网络…

竞赛选题 python+深度学习+opencv实现植物识别算法系统

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习的植物识别算法研究与实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;4分工作量&#xff1a;4分创新点&#xff1a;4分 &#x1f9ff; 更多…

基于Java微信小程序自驾游拼团设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f;感兴趣的可以先收藏起来&#xff0c;还…

27. 高级特性(下)

目录 一、为了类型安全和抽象而使用 newtype 模式二、使用类型别名创建类型同义词2.1 使用type关键赋予现有类型一个别名2.2 减少重复2.3 与Result<T, E>结合使用2.4 从不返回的 never type 三、高级函数和闭包3.1 函数指针3.2 返回闭包 四、宏4.1 宏和函数的区别4.2 mac…

python基础语法 003-3 数据类型元组

1 元组 1.1 元组含义 1.1.1 元组的表示 #元组的表示方法:() names ("xiaoyun", "xiaoming") print(names)--结果------- (xiaoyun, xiaoming) 1.1.2 空元组 #空元组 names () print(type(names)) print(len(names))----------------结果--------- &l…

安装vue开发者工具

浏览器控制台提示&#xff1a; 打开网址 GitHub - vuejs/devtools: ⚙️ Browser devtools extension for debugging Vue.js applications. 点击添加 上图地址&#xff1a;Installation | Vue Devtools 安装好了

群体优化算法---石墨烯优化算法介绍以及在期权定价上的应用(Black-Scholes模型来计算欧式期权的理论价格)

介绍 石墨烯算法是一种新兴的优化算法&#xff0c;灵感来自于石墨烯的结构和特性。石墨烯是一种由碳原子构成的二维蜂窝状晶格结构&#xff0c;具有优异的机械、电学和热学性能。石墨烯算法通过模拟石墨烯原子之间的相互作用和迁移&#xff0c;来求解复杂的优化问题 基本概念…

K8S -理解StatefulSet - 部署有状态应用

什么是 有状态服务和 无状态服务 有状态服务&#xff08;Stateful Service&#xff09;&#xff1a; 有状态服务是指在处理请求期间维护和跟踪用户状态或会话信息的服务。这意味着服务在多个请求之间保持状态&#xff0c;并且需要在请求之间共享和使用这些状态信息。通常&…

Websocket在Java中的实践——握手拦截器

在《Websocket在Java中的实践——最小可行案例》一文中&#xff0c;我们看到如何用最简单的方式实现Websocket通信。本文中&#xff0c;我们将介绍如何在握手前后进行干涉&#xff0c;以定制一些特殊需求。 在《Websocket在Java中的实践——最小可行案例》的基础上&#xff0c;…