gRPC教程与应用

news2024/12/23 22:47:26

gRPC是是谷歌一个开源的跨语言的RPC框架,面向移动和 HTTP/2 设计。

grpc中文网

在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。

gRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。

在这里插入图片描述
gRPC 默认使用 protocol buffers,这是 Google 开源的一套成熟的结构数据序列化机制。

在这里插入图片描述
protocol buffers能够生成RPC服务器,并使用proto文件来预先定义的消息格式。数据包是按照proto文件所定义的消息格式完成二进制码流的编码和解码。从而使基于RPC的服务器提供相关的接口,那么客户端通过服务端提供接口就可以访问服务器端的方法。

gRPC通过服务端-客户端方法来实现客户端直接访问服务端的方法。并以用户自定义的消息格式,完成字节的编码和解码。

gRPC 官方文档中文版

gRPC官网

gRPC 通过 protocol buffers来定义接口,将方法或者类注册到服务中,客户端也是使用同样的接口,只要接口连接成功就可以调用注册进服务的接口。

protocol buffers =是跨语言的,有自己的语法,通过自身语法定义接口定义语言来定义服务方法,并整合到其他语言,将程序的方法绑定protocol buffers的接口,实现跨语言访问。

protocol buffers教程

安装protocol compiler插件

以下步骤跟着教程来即可

本项目的gitee地址

go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2

在这里插入图片描述

如下图所示,在本机的GOPATH目录下下载了插件:

在这里插入图片描述

这两个插件是protocol buffer文件要使用的,用户将编译成对应语言的代码。这里是编译成go的代码。

了解rmi的可以知道该rpc只能在java中使用,这是由于rmi使用了java程序的接口,缺少扩展性,而protocol buffer则使用自身语法定义接口,并将接口绑定其他语言的方法,这样实现了语言的扩展性。

安装rpc服务器

go get google.golang.org/grpc

在这里插入图片描述

安装go语言的rpc服务器

gRPC 在 Go 语言中的安装与简单实践

rpc服务的实现可能有很多库,很多实现方式,如官方rpc官网上也提供了github的库。如下,

在这里插入图片描述
这里使用google官方的库。

编写protobuf规则

//proto语法版本 
syntax = "proto3";

//编译为对应语言
//第一个参数是目录位置分号隔开,第二个参数是服务名称
//option java_package = "io.grpc.examples";
option go_package = "./;golang";

package helloworld;

// The greeter service definition.
//service定义接口(方法)
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
//message定义结构体或者类
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

在这里插入图片描述
在这里插入图片描述

切换到proto文件目录并生成代码

在这里插入图片描述
protocol buffer文件以proto为后缀,切换到对应目录,执行插件。

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./grpc-test/make.proto

protoc是插件命令,grpc-test/make.proto是proto文件位置。

在这里插入图片描述
在这里插入图片描述
执行完成后生成了后缀带.pb的两个文件,如下:

在这里插入图片描述
该步骤对应官网的命令行步骤:

在这里插入图片描述

到此go-rpc的服务端代码已经自动生成了(根据自定义的规则proto文件生成),接下来就是启动rpc服务器实例,将方法注册到服务器实例即可。

在这里插入图片描述
生成服务器实例

注意生成的文件一个是grpc.pb,一个是.pb前者是接口,后者是rpc服务器。
在这里插入图片描述

根据grpc.pc提供的类实现服务器实例:

在这里插入图片描述
只需要实现该结构体即可,实现其SayHello方法。自定义Server实现方法。

在这里插入图片描述

实现后注意前面有继承关系的ICON才算成功。

方法注册到服务器

package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"grpc-test/pb"
	"net"
)

// 生成服务器实例(自定义server实现生成的server)
type Server struct {
	pb.UnimplementedGreeterServer
}

// SayHello 将grpc接口绑定程序方法(借助接口实现,接口必须是grpc接口中注册了的)
// 方法在proto文件中定义了
func (s *Server) SayHello(context.Context, *pb.HelloRequest) (*pb.HelloReply, error) {
	return &pb.HelloReply{Message: "conect server successful"}, nil
}

// 运行服务
func main() {
	//基于tcp实现
	listen, err := net.Listen("tcp", ":1099")
	if err != nil {
		fmt.Println("failed to listen", err)
	}
	//创建grpc服务
	server := grpc.NewServer()
	
	//*************** 关键  **********
	//注册自定义方法 
	pb.RegisterGreeterServer(server, &Server{})
	// *********************************
	
	//启动服务
	err = server.Serve(listen)
	if err != nil {
		fmt.Println("failed to serve", err)
		return
	}
}

客户端连接服务端

package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"grpc-test/pb"
)

func main() {
	//配置连连接参数(无加密)
	dial, _ := grpc.Dial("localhost:1099", grpc.WithTransportCredentials(insecure.NewCredentials()))
	defer dial.Close()
	//创建客户端连接
	client := pb.NewGreeterClient(dial)
	//通过客户端调用方法
	res, _ := client.SayHello(context.Background(), &pb.HelloRequest{Name: "xiaoxu"})
	fmt.Println(res.GetMessage())

}

客户端连接后直接通关接口调用方法,服务器端也需要存在如下的两个文件。
在这里插入图片描述
客户端调用的是如下文件提供的接口,而改接口被rpc服务器封装,并在服务器端与服务器端方法绑定,grpc封装了传输的细节,因此使用是来就想调用本地方法一样方便。

运行结果如下,
在这里插入图片描述
返回了服务端的信息,

在这里插入图片描述

案例gitee地址

原理剖析

grpc是rpc的一种具体实现方式,采用服务端和客户端通讯的方式,和HTTP的不同在于规避了许多无关部分,例如HTTP的b/c架构需要借助浏览器,因此远程调用时在程序中必须模拟浏览器访问再解析数据。而grpc直接实现了新的服务器,并允许用户自定义接口,在服务器中暴露这些接口,在程序中整合grpc服务器,然后将接口绑定到程序的方法,客户端在连接rpc服务器是调用接口,则会直接指向服务器程序的方法,因此就行在本地调用一样。

在这里插入图片描述
由protobuf生成的接口,程序中实现该接口。

protocol buffer配置文件,定义接口规则,用于生成自定义的接口:

在这里插入图片描述
.proto文件定义生成规则,在.pb文件生成定制化接口。

gprc的跨语言性

grpc是使用期本身的语法定义接口的,在上面的例子中使用了go语言,将接口绑定到go语言的接口中,那么如果将grpc的接口绑定到其他语言中也是可以使用的。

由于Go语言都是基于源码进行的,在其他语言中需要下载protobuf的工具包,帮助将proto的接口转换为对应语言的接口。

转换其他语言的接口主要在于命令不同:

option java_package = "com.zy.tutor";  // 生成的java文件的包名 
option java_outer_classname = "xunjianProtos"; // 生成的java文件的类名

//插件生成命令
protoc --java_out . plateDetection.proto
<dependency>
	<groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>3.19.1</version>
</dependency>

grpc支持很多语言,不在一一赘述。

propto数据类型

每种语言都有自己的独特的数据类型,如java的了类,go的结构体,显然protobuf是无法满足所有的语言的数据结构的,因此一些特殊的数据结构需要转化。proto直接的数据结构如下:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

参考自:proto文件详解感谢作者@Sacred

那么最复杂的数据类型只能序列化为STRING再反序列化了。

案例

  • 下载protobuf插件和grpc工具包

  • 定义proto文件约定接口
syntax = "proto3";

//编译为对应语言
//option java_package = "io.grpc.examples";
option go_package = "./;protoInterface";

package protoInterface;

// 定义接口
service Interface {
  // 方法1
  rpc GetProduct (Request) returns (Response) {}
  // 方法2
  rpc GetOrder (Request) returns (Response) {}

}

// 定义数据类型
message Request {
  string paramString = 1;
}

//
message Response {
  string messageString = 1;
}
  • 插件命令将proto文件转为接口与服务
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./build.proto

插件命令若是windows则在bat文件下,若是linux则在sh文件下。

  • 服务层逻辑
package service

import "encoding/json"

type Product struct {
	Id              int64  `json:"id" xorm:"not null pk autoincr comment('主键 id') BIGINT"`
	CustomerId      int64  `json:"customer_id" xorm:"comment('客户 id') BIGINT(20)"`
	ProductName     string `json:"product_name" xorm:"comment('产品名称') VARCHAR(20)"`
	AvailableAreaId int    `json:"available_area_id"` // 可用区id
	ResourcePoolId  int    `json:"resource_pool_id"`  //资源池id
	ProductId       int64  `json:"product_id"`        //产品id
	CardType        string `json:"card_type"`         //显卡型号
	CardNum         int    `json:"card_num"`          //显卡数量
	ContainerName   string `json:"container_name"`    // 容器名称
	ContainerId     string `json:"container_id"`      // 容器id
	CreatedAt       string `json:"created_at" xorm:"comment('创建时间') DATETIME created"`
	UpdatedAt       string `json:"updated_at" xorm:"comment('修改时间') DATETIME updated"`
}

func (Product) DefaultProduct() Product {
	return Product{
		Id:              1,
		CustomerId:      1,
		ProductName:     "xiaoxu",
		AvailableAreaId: 1,
		ResourcePoolId:  1,
		ProductId:       1,
		CardType:        "bike",
		CardNum:         1,
		ContainerName:   "xiaoxu",
		ContainerId:     "1",
		CreatedAt:       "2023",
		UpdatedAt:       "2023",
	}
}

func (Product) ToJSON(product Product) string {
	marshal, err := json.Marshal(product)
	if err != nil {
		panic(err)
	}
	return string(marshal)
}

func (Product) ToSTRUCT(product string) Product {
	var pro Product
	err := json.Unmarshal([]byte(product), &pro)
	if err != nil {
		panic(err)
	}
	return pro
}

  • grpc服务注册服务层逻辑
package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"grpc-demo/protobuf"
	"grpc-demo/service"
	"net"
)

// Server 实现服务类
type Server struct {
	protoInterface.UnimplementedInterfaceServer
}

// GetProduct
func (Server) GetProduct(context.Context, *protoInterface.Request) (*protoInterface.Response, error) {
	//获取程序中的返回值
	param := service.Product{}
	product := param.DefaultProduct()
	json := param.ToJSON(product)
	return &protoInterface.Response{
		MessageString: json,
	}, nil

}

// GetOrder
func (Server) Util(context.Context, *protoInterface.Request) (*protoInterface.Response, error) {
	return nil, nil
}

// 运行服务
func main() {
	//基于tcp实现
	listen, err := net.Listen("tcp", ":1099")
	if err != nil {
		fmt.Println("failed to listen", err)
	}
	//创建grpc服务
	server := grpc.NewServer()
	//注册自定义方法
	protoInterface.RegisterInterfaceServer(server, &Server{})
	//启动服务
	err = server.Serve(listen)
	if err != nil {
		fmt.Println("failed to serve", err)
		return
	}
}

  • 客户端调用
package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"grpc-demo/protobuf"
	"grpc-demo/service"
)

func main() {
	//配置连连接参数(无加密)
	dial, err := grpc.Dial("localhost:1099", grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		println("failed grpc connect", err)
	}
	defer dial.Close()
	//创建客户端连接
	client := protoInterface.NewInterfaceClient(dial)
	//通过客户端调用方法
	res, err := client.GetProduct(context.Background(), &protoInterface.Request{
		ParamString: "hello",
	})
	if err != nil {
		println("failed grpc recive err", err)
	}
	//打印接受的字符
	fmt.Printf("%v", res)
	/*
		//获取带product结构体在反序列化
		param := service.Product{}
		product := param.ToSTRUCT(res.MessageString)
		fmt.Println(product)
	*/

}

启动grpc服务后,启动客户端请求,如下返回的字符流。
在这里插入图片描述
反序列化后得到结构体

//获取带product结构体在反序列化
param := service.Product{}
product := param.ToSTRUCT(res.MessageString)
fmt.Println(product)

在这里插入图片描述

因此只要在客户端封装grpc客户端就可以使用该客户端调用方法,就先高调用本地方法一样。

go-grpc

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

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

相关文章

python3+requests+unittest接口自动化测试

1.环境准备 python3 pycharm编辑器 2.框架目录展示 &#xff08;该套代码只是简单入门&#xff0c;有兴趣的可以不断后期完善&#xff09; &#xff08;1&#xff09;run.py主运行文件&#xff0c;运行之后可以生成相应的测试报告&#xff0c;并以邮件形式发送&#xff1b;…

【C++进阶】红黑树实现

文章目录 红黑树的概念红黑树的性质红黑树节点的定义红黑树结构红黑树的插入1.按照二叉搜索的树规则插入新节点2.进行旋转和变色源码 红黑树的验证中序遍历判断是否满足二叉搜索树判断是否满足红黑树 完整源码 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但…

基于spss的多元统计分析 之 单/双因素方差分析 多元回归分析(1/8)

实验目的&#xff1a; 1&#xff0e;掌握单样本t检验、两样本t检验、配对样本t检验、单因素方差分析、多元回归分析的基本原理&#xff1b; 2&#xff0e;熟悉掌握SPSS软件或者R软件关于单因素、多因素方差分析、多元回归分析的基本操作&#xff1b; 3&#xff0e;利用实验指导…

2.3C++保护成员

C 保护成员 在C中&#xff0c;可以使用保护成员 protected&#xff0c;来提高代码的安全性。 我用大白话解释一下什么是保护成员&#xff1a;说白了就是为了防止其他类直接访问或修改其成员加的一个措施。 目的是保护&#xff0c;成员的私有性和可见性。 C 类的保护 可以为…

web 语音通话 jssip

先把封装好的地址安上&#xff08;非本人封装&#xff09;&#xff1a;webrtc-webphone: 基于JsSIP开发的webrtc软电话 jssip中文文档&#xff1a;jssip中文开发文档&#xff08;完整版&#xff09; - 简书 jssip使用文档&#xff1a;&#xff08;我没有运行过&#xff0c;但…

Nginx服务器,在window系统中的使用(前端,nginx的应用)

简介&#xff1a;Nginx是一个轻量级、高性能的HTTP和反向代理web服务器&#xff0c;且支持电子邮件&#xff08;IMAP/POP3&#xff09;代理服务&#xff0c;特点是占用内存少&#xff0c;并发能力强&#xff0c;给我们来了很多的便利&#xff0c;国内大部分网站都有使用nginx&a…

18款奔驰S350升级后排座椅记忆功能,提升您乘坐舒适性

带有记忆功能的座椅可以存储三个的座椅设置以及行车电脑中的舒适性设置。只要按一下按钮就可以跳到记忆模式&#xff0c;让座椅回到上一次设置。

使用 BigQuery Omni,发现跨云地理空间分析的优势

【本文由 Cloud Ace 整理发布。Cloud Ace 是谷歌云全球战略合作伙伴&#xff0c;拥有 300 多名工程师&#xff0c;也是谷歌最高级别合作伙伴&#xff0c;多次获得 Google Cloud 合作伙伴奖。作为谷歌托管服务商&#xff0c;我们提供谷歌云、谷歌地图、谷歌办公套件、谷歌云认证…

第十章详解synchronized锁升级

文章目录 升级的流程为什么要引入锁升级这套流程多线程访问情况具体流程 轻量级锁如何使用CAS实现轻量级锁CAS加锁成功CAS加锁失败CAS进行解锁 总结何时变为重量级锁 锁膨胀自旋优化 偏向锁主要作用偏向状态测试撤销偏向锁 撤销 - 调用对象 hashCode撤销 - 其它线程使用对象撤销…

js:codemirror实现在线代码编辑器代码高亮显示

CodeMirror is a versatile text editor implemented in JavaScript for the browser. It is specialized for editing code, and comes with a number of language modes and addons that implement more advanced editing functionality. 译文&#xff1a;CodeMirror是一个多…

第二章:软件工程师必备的网络基础

目录 一、网线的制作 二、集线器、交换机介绍 三、路由器的配置 一、网线的制作 1.1、水晶头 ​​​ 1.2、网线钳 1.3、网线的标准 T568A标准&#xff08;交叉线&#xff09;&#xff1a; 适用链接场合&#xff1a;电脑-电脑、交换机-交换机、集线器-集线器 接线顺序&…

【正点原子STM32连载】第三十九章 触摸屏实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html# 第三…

有源电力滤波器及配电能效平台在污水处理厂中的应用

【摘要】为减少污水处理设备产生的各次谐波&#xff0c;通过确定主要谐波源&#xff0c;检测和计算谐波分量&#xff0c;采用有源电力滤波器进行谐波治理&#xff0c;大幅降低了电力系统中的三相电流畸变率&#xff0c;提高了电能质量&#xff1b;抑制了谐波分量&#xff0c;减…

doris docker部署和本地化部署 1.2.4.1版本

写在前面 以下操作语句按顺序执行即可&#xff0c;注意切换目录的命令一定记得执行&#xff0c;如果需要改动的地方会有${}注释&#xff0c;其余不需要任何改动&#xff0c;默认安装版本为1.12.4&#xff08;稳定版&#xff09; 本地化部署 下载 # 创建目录 mkdir /data/sof…

软件测试日常工作和前景是怎么样的?

笔者从测试的工作情况&#xff0c;职业发展&#xff0c;还有测试的工作日常等等来给大家讲解一下软件测试到底是什么样的工作&#xff1f; 通俗来说软件测试工程师就相当于一个质检员&#xff0c;专门处理软件测试质量的工作&#xff0c;不管是功能测试也好&#xff0c;性能测…

BK7231N开发平台原厂烧录工具使用说明

BK7231N开发平台原厂烧录工具使用说明 烧录流程介绍 1.打开原厂烧录工具 以管理员身份打开名为 bk_writer_gui_V1.6.3.exe 的可执行文件。 2. 烧录对象 烧录对象选择 BK7231n 3.烧录地址 当我们烧录UA文件的时候&#xff0c;需要把起始地址设置为&#xff1a; 0X00011000。…

Windows提示“找不到rgss202j.dll”怎么办?

Rgss202j.dll文件是Windows操作系统最重要的系统文件之一&#xff0c;它包含了一组程序和驱动函数。如果此文件丢失或损坏&#xff0c;驱动程序将无法正常工作&#xff0c;并且相应的应用程序也将无法正常启动且运行。通常情况下&#xff0c;造成Rgss202j.dll文件无法找到的原因…

爬虫 - ProtoBuf 协议

一、抓取请求 以下是请求的大致内容&#xff1a; 是乱码&#xff0c;需要解析。 二、解析 通过分析 request 和 response 的 Content-Type: application/x-protobuf 得知&#xff1a;使用了谷歌的 protobuf 协议来传输数据&#xff0c;需要破解。 大致破解过程&#xff…

随时随地保持连接:数字游民适用的远程桌面

随着世界迅速适应数字革命&#xff0c;一种全新的职业——数字游民应运而生。数字游民指利用技术远程办公的专业人群&#xff0c;这是一种允许人们在旅行中办公、不受地点限制的工作生活方式。游牧式工作生活趋势并非一时的风尚&#xff0c;而是我们工作观念的彻底转变&#xf…

MUR8060PT-ASEMI快恢复二极管MUR8060PT

编辑-Z MUR8060PT在TO-247封装里采用的2个芯片&#xff0c;其尺寸都是140MIL&#xff0c;是一款高耐压大电流快恢复二极管。MUR8060PT的浪涌电流Ifsm为600A&#xff0c;漏电流(Ir)为10uA&#xff0c;其工作时耐温度范围为-55~150摄氏度。MUR8060PT采用抗冲击硅芯片材质&#x…