现在非常流行微服务,而 RPC 框架是微服务中不可或缺的一环,gRPC 是其中一个非常出色的 RPC 框架,所以借此机会来记录一下 gRPC 在 Go 语言中的安装使用以及运用。

PS.刚弄好 WSL 开发环境不久,所以这次都是在 WSL 环境下进行的。

gRPC 是什么

RPC

RPC 是远程过程调用(Remote Procedure Call)的缩写形式。SAP 系统 RPC 调用的原理其实很简单,有一些类似于三层构架的 C/S 系统,第三方的客户程序通过接口调用 SAP 内部的标准或自定义函数,获得函数返回的数据进行处理后显示或打印。

gRPC

更多人可能接触的更多的是基于 REST 的通信。我们已经看到,REST 是一种灵活的体系结构样式,它定义了对实体资源的基于CRUD的操作。 客户端使用请求/响应通信模型跨 HTTP 与资源进行交互。尽管 REST 是广泛实现的,但一种较新的通信技术 gRPC 已在各个生态中获得巨大的动力。

gRPC,其实就是 RPC 框架的一种,前面带了一个 g ,代表是 RPC 中的大哥,龙头老大的意思,另外 g 也有 global 的意思,意思是全球化比较 fashion ,是一个高性能、开源和通用的 RPC 框架,基于 ProtoBuf(Protocol Buffers) 序列化协议开发,且支持众多开发语言。面向服务端和移动端,基于 HTTP/2 设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。

在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。与许多 RPC 系统类似,gRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。

gRPC的安装

在了解完 RPC 以及 gRPC 之后我们就要开始进行 gRPC 的安装,其实 gRPC 的安装非常简单,直接拉取第三方包就可以了,难点是 protobuf 的安装

protobuf (protocol buffer) 是谷歌内部的混合语言数据标准。通过将结构化的数据进行序列化(串行化),用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

//go mod拉一下这两个库
google.golang.org/grpc
google.golang.org/protobuf
wget https://github.com/protocolbuffers/protobuf/releases/download/v21.1/protoc-21.1-linux-x86_64.zip

将解压后得到的protoc二进制文件移动到$GOPATH/bin

PS.一定要配置好 GOPATH ,不然无法使用 protoc

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

在安装好这两个之后检查一下 $GOPATH/bin 路径中是否有相对应的二进制文件,如果没有就去 /pkg/mod 中找到这两个包,运行 go build 编译成二进制文件再放进 $GOPATH/bin

此时基本已经大功告成,我们在终端输入 protoc --version 检查版本,若没问题就表明我们 protobuf 安装成功了

现在我们就可以打开一个新项目,愉快的使用 gRPC 进行开发

gRPC 的使用

为了让大家更加清楚,这次我会在之前使用 http 框架 gin 的项目上进行开发,并且使用更改密码这个功能来进行示范。

首先我们要创建一个 rpc 文件夹,然后其中还会有 server client pd文件夹,分别放有服务端,客户端以及 protobuf 自动生成的代码。

编写 proto 文件

关于 proto 文件的语法就不在这里赘述了,感兴趣可以上网查一下

syntax = "proto3";package changePW;option go_package = "./changePW";message changeReq {string old_password = 1;string new_password = 2;string username = 3;
}message changeRes {bool status = 1;string msg = 2;
}service changePW {rpc changePW (changeReq) returns (changeRes);
}

因为每次都输入命令行语句非常麻烦,所以我使用的是一个 sh 脚本,在文件中放下面的代码

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

在终端中 ./build.sh.cmd 后自动生成代码

编写服务端代码

type server struct {changePW.UnimplementedChangePWServer
}func main() {err := dao.InitDB()listen, err := net.Listen("tcp", ":50002")if err != nil {log.Println("net.Listen ERR: ", err)return}s := grpc.NewServer()changePW.RegisterChangePWServer(s, &server{}) //注册这一个服务if err = s.Serve(listen); err != nil { //监听log.Println(err)return}
}func (s *server) ChangePW(ctx context.Context, req *changePW.ChangeReq) (res *changePW.ChangeRes, err error) {res = &changePW.ChangeRes{Status: false,Msg:    "更改密码错误",}user, err := dao.SelectUserByUsername(req.Username)if err != nil {if err == sql.ErrNoRows {return res, nil}return res, err}if user.Password != req.OldPassword {return &changePW.ChangeRes{Status: false,Msg:    "密码不符",}, nil}err = dao.UpdatePassword(req.Username, req.NewPassword)if err != nil {return &changePW.ChangeRes{Status: false,Msg:    "更改密码错误",}, nil}return &changePW.ChangeRes{Status: true,Msg:    "成功",}, nil
}

其中数据访问层的代码需要自行编写,值得一提的是必须在服务端中有初始化数据库的动作,不然会报 panic 。

客户端

func CallChangePw(endpoint string, oldPassword string, newPassword string, username string) (res *changePW.ChangeRes) {conn, err := grpc.Dial(endpoint, grpc.WithTransportCredentials(insecure.NewCredentials()))if err != nil {log.Println(err)return &changePW.ChangeRes{Status: false,Msg:    err.Error(),}}defer conn.Close()client := changePW.NewChangePWClient(conn)res, err = client.ChangePW(context.Background(),&changePW.ChangeReq{OldPassword: oldPassword,NewPassword: newPassword,Username:    username,},)if err != nil {log.Println(err)return &changePW.ChangeRes{Status: false,Msg:    err.Error(),}}fmt.Println("res = ", res)return res
}

API层

在此层使用 gin 框架。

func changePasswordRPC(ctx *gin.Context) {oldPassword := ctx.PostForm("old_password")newPassword := ctx.PostForm("new_password")iUsername, _ := ctx.Get("username")username := iUsername.(string)l1 := len([]rune(newPassword))if l1 > 16 {tool.RespErrorWithDate(ctx, "密码请在16位以内")return}res := client.CallChangePw("127.0.0.1:50002", oldPassword, newPassword, username)if res.Status == true {tool.RespSuccessfulWithDate(ctx, res.Msg)return}tool.RespErrorWithDate(ctx, res.Msg)return
}

最后在路由中进行调用

userGroup := engine.Group("/user")
{userGroup.Use(auth)userGroup.POST("/password", changePassword) //修改密码userGroup.POST("/rpc/password", changePasswordRPC)
}

结语

如果有没弄清楚的地方欢迎大家向我提问,我都会尽力解答

这是我的GitHub主页 github.com/L2ncE

欢迎大家Follow/Star/Fork三连

参考

https://zhuanlan.zhihu.com/p/411315625

gRPC 在 Go 语言中的安装与简单实践相关推荐

  1. r语言barplot函数图中加标签_R语言中绘制条形图的简单方法

    原标题:R语言中绘制条形图的简单方法 条形图(bar chart)是用宽度相同的条形的高度或长短来表示数据多少的图形.它主要用来展示不同分类(横轴)下某个数值型变量(纵轴)的取值.在实际中,条形图主要 ...

  2. %6f 在c语言中的作用,最简单的C程序设计 1.实验目的 ①掌握C语言中使用最多的一种语..._考试资料网...

    最简单的C程序设计 1.实验目的 ①掌握C语言中使用最多的一种语句--赋值语句的使用方法. ②掌握各种类型数据的输入输出的方法,能正确使用各种格式转换符. 2.实验内容和步骤 掌握各种格式转换符的正确 ...

  3. c语言中的加减乘除字母,简单的c语言加减乘除运算

    简单的c语言加减乘除运算 答案:6  信息版本:手机版 解决时间 2019-10-03 12:11 已解决 2019-10-03 00:06 简单的c语言加减乘除运算 最佳答案 2019-10-03 ...

  4. c#语言中读取txt文件,简单的c#文本文件读写-.NET教程,C#语言

    system.io命名空间中的类为托管应用程序提供文件以及其他形式的输入输出.托管i/o的基本构件是流,而流是字节导向的数据的抽象表示.流通过system.io.stream类表示. system.i ...

  5. webbench 下载_Ubuntu中webbench安装及简单使用

    Webbench是Linux下的一个网站压力测试工具,能测试处在相同硬件上,不同服务的性能以及不同硬件上同一个服务的运行状况.webbench的标准测试可以向我们展示服务器的两项内容:每分钟相应请求数 ...

  6. c语言中生日蛋糕图片大全,简单生日蛋糕图片大全

    蛋糕是一种面食,通常是甜的,典型的蛋糕是以烤的方式制作出来.下面是学习啦为大家准备的简单生日蛋糕图片,希望可以帮助大家! 生日祝福语: 1.摇曳的烛光,点亮你的生日;深情的吟唱,寄予我无限的祝福;漫天 ...

  7. c语言中求奇数的简单代码

    #include <stdio.h> int main() {int a = 0;while(a<100){if(a%2 != 0)//%表示求余数printf("%d & ...

  8. Flume监控之Ganglia安装与简单实践

    写在前面: 博主是一名大数据的初学者,昵称来源于<爱丽丝梦游仙境>中的Alice和自己的昵称.作为一名互联网小白,写博客一方面是为了记录自己的学习历程,一方面是希望能够帮助到很多和自己一样 ...

  9. c语言 r语言 java,R语言rJava包安装载入及JAVA环境配置

    rJava 包的安装与载入 一般文本分词的教程都会贴出: install.packages("rJava") library(rJava) 来引导我们装载rJava包,运行inst ...

最新文章

  1. C# 仿金山毒霸启动和关闭淡入淡出效果
  2. django orm级联_django+jquery 实现级联选择菜单
  3. 致27岁的老光棍天空
  4. mysql连接报错:The server time zone value ‘Öйú±ê׼ʱ¼ä‘ is unrecognized or represents more than one time
  5. 单元测试怎么测试线程_单元测试线程代码的5个技巧
  6. 【51Nod - 1163】最高的奖励 (贪心+优先队列 或 妙用并查集)
  7. SAP License:集团化企业的协同管理
  8. python学习网站-有哪些值得推荐的Python学习网站?
  9. Mvc6 错误Microsoft.AspNet.Http.Features.IRequestIdentifierFeature
  10. c高级语言程序设计课程设计报告,高级语言程序设计 课程设计报告
  11. Youtube油管视频类别标签列表
  12. Python3,1行代码,去除图片的背景图,确实香。
  13. office如何从非第一页开始插入页码
  14. android计步器简书,iOS中计步器的实现方案及原理
  15. 【数据库篇】MySQL InnoDB ibd 文件格式解析
  16. 蓝牙芯片|伦茨科技-智能蓝牙BLE5.2芯片ST17H66
  17. 电视PPTV服务器响应异常,pptv出现异常错误怎么解决
  18. 软考高级系统架构设计师:论面向服务的架构及其应用
  19. 时间管理:瞎忙和高效的区别
  20. 【R】葡萄牙森林火灾(数据可视化回归分析)

热门文章

  1. linux网卡驱动离线安装_在linux下安装网卡驱动的方法
  2. Alientek I.MX6UL Linux- 第七章 ARM汇编基础
  3. 用Google Brain的机器学习项目:Magenta,教神经网络学抖音小姐姐作曲。
  4. wallpaper使用教程,从注册到安装
  5. opencv2.0的移植 OMAP4460 FPU
  6. 用frontpage2003写HTML指令(一):指令集
  7. radmin不能发送Ctrl+Alt+Del的解决办法
  8. 瑞博奥IPO过会:年营收2.85亿 黄若磐家族均为美国籍
  9. 二进制负数的补码为什么是符号位不变,其他位取反加一?
  10. 零信任-深信服零信任aTrust介绍(5)