go-grpc 基本使用

gRPC是什么?#

gRPC是什么可以用官网的一句话来概括

A high-performance, open-source universal RPC framework

所谓RPC(remote procedure call 远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型。使用的时候客户端调用server端提供的接口就像是调用本地的函数一样。如下图所示就是一个典型的RPC结构图。

RPC通信#

gRPC有什么好处以及在什么场景下需要用gRPC
既然是server/client模型,那么我们直接用restful api不是也可以满足吗,为什么还需要RPC呢?下面我们就来看看RPC到底有哪些优势

gRPC vs. Restful API#

gRPC和restful API都提供了一套通信机制,用于server/client模型通信,而且它们都使用http作为底层的传输协议(严格地说, gRPC使用的http2.0,而restful api则不一定)。不过gRPC还是有些特有的优势,如下:

gRPC可以通过protobuf来定义接口,从而可以有更加严格的接口约束条件。

另外,通过protobuf可以将数据序列化为二进制编码,这会大幅减少需要传输的数据量,从而大幅提高性能。
gRPC可以方便地支持流式通信(理论上通过http2.0就可以使用streaming模式, 但是通常web服务的restful api似乎很少这么用,通常的流式数据应用如视频流,一般都会使用专门的协议如HLS,RTMP等,这些就不是我们通常web服务了,而是有专门的服务器应用。)

Protobuf是什么#

官方文档: https://developers.google.com/protocol-buffers

Protobuf实际是一套类似Json或者XML的数据传输格式和规范,用于不同应用或进程之间进行通信时使用。通信时所传递的信息是通过Protobuf定义的message数据结构进行打包,然后编译成二进制的码流再进行传输或者存储。

Protobuf的优点#

相比较而言,Protobuf有如下优点:

  • 足够简单
  • 序列化后体积很小:消息大小只需要XML的1/10 ~ 1/3
  • 解析速度快:解析速度比XML快20 ~ 100倍
  • 多语言支持
  • 更好的兼容性,Protobuf设计的一个原则就是要能够很好的支持向下或向上兼容

安装Protobuf#

  1. 官网下载二进制文件
    https://github.com/protocolbuffers/protobuf/releases

根据自己的系统版本下载指定的稳定版本文件

我这边是 MAC 就下载 protoc-3.11.4-osx-x86_64.zip文件

  1. 添加可执行文件到环境变量

  2. 为了基础protobuf文件,使用protoc工具编译出go相关文件,需要安装一个插件

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

GRPC示例#

安装grpc#

Copy
$ go get -u google.golang.org/grpc

GRPC服务端#

目录结构

Copy
. ├── main.go // 入口文件 ├── pbfile // protobuf 中间文件 │   └── Prob.proto ├── pbservices // 根据中间文件生成的go文件 │   └── Prob.pb.go └── services // 根据生成的go文件的实现 └── Prob.go

protobuf 中间文件

Copy
// proto 文件版本 syntax = "proto3"; // 生成文件的包名 package services; // 请求结构体 message ProbRequest { int32 Pid = 1; } // 响应结构体 message ProbResponse { float Price = 1; } // 定义rpc接口 service ProbService { rpc GetProductPrice (ProbRequest) returns (ProbResponse) }

使用中间文件生成go文件

Copy
$ cd pbfile/ $ protoc --go_out=plugins=grpc:../pbservices Prob.proto

实现生成的go文件的接口

Copy
// services/Prob.go package services import ( "context" "pbservices" ) type ProbService struct { } func (this *ProbService) GetProductPrice(context.Context, request *pbservices.ProbRequest) (*pbservices.ProbResponse, error) { return &pbservices.ProbResponse{Price: 10}, nil }

创建rpc服务文件

Copy
package main import ( "pbservices" "services" "google.golang.org/grpc" "log" "net" ) func main() { // 服务端启用安全证书 //cred, err := credentials.NewServerTLSFromFile("./keys/server.crt", "./keys/server.key") //if err != nil { // log.Fatal(err) //} // 创建服务 //rpcserver := grpc.NewServer(grpc.Creds(cred)) rpcserver := grpc.NewServer() // 注册 pbservices.RegisterProbServicesServer(rpcserver, &services.ProbService{}) // 启动监听 lis, err := net.Listen("tcp", ":8081") if err != nil { log.Fatal(err) } err = rpcserver.Serve(lis) if err != nil { log.Fatal(err) } }

GRPC客户端#

目录结构

Copy
. ├── main.go // 入口文件 └── pbservices // 根据中间文件生成的go文件 └── Prob.pb.go

客户端实现#

Copy
package main import ( "context" "fmt" "pbservices" "google.golang.org/grpc" "log" ) func main() { // 启用安全证书 //cred, err := credentials.NewClientTLSFromFile("./keys/server.crt", "mazhichao.com") //if err != nil { // log.Fatal(err) //} //conn, err := grpc.Dial(":8081", grpc.WithTransportCredentials(cred)) // grpc.WithInsecure() 忽略安全 conn, err := grpc.Dial(":8081", grpc.WithInsecure()) if err != nil { log.Fatal(err) } defer conn.Close() client := pbservices.NewProbServicesClient(conn) req := &pbservices.ProbRequest{Pid: 1} response, err := client.GetProductPrice(context.Background(), req) if err != nil { log.Fatal(err) } fmt.Println(response.Price) }
posted @   ZhiChao&  阅读(1676)  评论(0编辑  收藏  举报
编辑推荐:
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
阅读排行:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 用 C# 插值字符串处理器写一个 sscanf
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
点击右上角即可分享
微信分享提示
CONTENTS