grpc+protobuf的一个demo示例
1.需要保证电脑中安装了protobuf安装教程
2.如果出现报错请看博客protobuf报错问题解决
3.demo地址:demo
简介:
rpc微服务,grpc是一种开源的高性能RPC框架,能够运行在任何环境中,最初由谷歌进行开发,它使用HTTP2作为传输协议。grpc让客户端可以像调用本地方法一样调用其他服务器上的服务应用程序,可以更容易的创建分布式应用程序和服务。能让我们更容易的编写跨语言的分布式代码。本示例使用protocol buffers(简写:protobuf),使用protobuf可以高效的序列化,简单的IDL(接口描述语言)并且容易进行接口更新。
一、安装gRPC
-
安装grpc执行命令
go get google.golang.org/grpc@latest
-
安装Protocol Buffers v3
安装方法就是文章开头1的protobuf链接
-
安装插件
安装go语言插件,这个插件会根据.proto文件生成一个后缀为.pb.go的文件:
该文件文件中包含定义的类型及其序列化方法go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
安装grpc插件,这个插件会生成_grpc.pb.go后缀的文件:
该文件中包含接口类型(或存根),提供给客户端调用的服务方法;服务器需要实现的接口类型go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
-
默认将插件安装到
$GOPATH/bin
路径下,具体配置在文章开头第1条安装方式博客中已经写好
二、基本使用
-
按照博客写完demo后的目录结构:
user@C02FP58GML7H grpc-demo-master % tree . ├── LICENSE ├── README.en.md ├── README.md ├── client │ ├── grpc_client.go │ └── pb │ ├── product.pb.go │ └── product_grpc.pb.go ├── go.mod ├── go.sum ├── grpc_server.go ├── pb │ ├── product.pb.go │ └── product_grpc.pb.go ├── pbfile │ └── product.proto └── service └── product.go
-
创建proto文件
-
创建一个名为project-demo的go项目
-
在project-demo目录下创建文件夹pbfile
-
在pbfile目录下创建文/定义文件product.proto
-
文件内容如下:
// 声明protobuf版本 syntax = "proto3"; // option go_package = "path;name"; path 表示生成的go文件的存放地址,会自动生成目录 // name表示生成的go文件所属的包名 option go_package = "../pb"; package pb; // 请求体 message ProductRequest { int32 prod_id = 1; } // 响应体 message ProductResponse { int32 prod_stock =1; } // 定义服务体 service ProductService { // 定义方法 rpc GetProductStock(ProductRequest) returns (ProductResponse) {} }
-
-
在控制台生成pb文件夹,文件夹中.pb.go和_grpc.pb.go文件
- 切换到pbfile目录下:cd pbfile(demo链接在博客头部,此事例按照demo上面显示的进行讲解)
- 需要执行命令:
protoc --go_out=./ --go_grpc=./ product.proto
- 项目下会自动生成pb文件夹和
product.pb.go
、product_grpc.pb.go
两个文件 - 注:demo中的示例已经生成好,如有需要可删除后自行操作,重新生成
-
创建服务端
-
在project-demo下创建service文件夹
-
在service下创建product.go文件,produc.go文件实现了product.protoc定义的接口
-
product.go文件代码:
package service import ( "context" "projectbao/pb" ) var ProductService = &productService{} type productService struct { pb.UnimplementedProductServiceServer } func (p *productService) GetProductStock(context context.Context, request *pb.ProductRequest) (*pb.ProductResponse, error) { stock := p.GetStockById(request.ProdId) return &pb.ProductResponse{ProdStock: stock}, nil } func (p *productService) GetStockById(id int32) int32 { return id }
-
在project-demo下创建grpc_server.go文件,注册/创建grpc服务
-
grpc_server.go文件代码:
package main import ( "fmt" "log" "net" "projectbao/pb" "projectbao/service" "google.golang.org/grpc" ) func main() { rpcServer := grpc.NewServer() pb.RegisterProductServiceServer(rpcServer, service.ProductService) listion, err := net.Listen("tcp", ":8002") if err != nil { log.Fatal("启动监听出错", err) } err = rpcServer.Serve(listion) if err != nil { log.Fatal("启动服务器出错", err) } fmt.Println("启动grpc服务端成功") }
-
-
创建客户端
-
在project-demo下创建client文件夹
-
把pb文件夹复制到client目录下一份
-
在client文件夹下创建客户端grpc_client.go文件
-
client.go文件代码:
package main import ( "context" "fmt" "log" "projectbao/pb" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) func main() { conn, err := grpc.Dial(":8002", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatal("服务端出错", err) } defer conn.Close() prodClient := pb.NewProductServiceClient(conn) request := &pb.ProductRequest{ ProdId: 100, } stockReponse, err := prodClient.GetProductStock(context.Background(), request) if err != nil { log.Fatal("查询库存出错", err) } fmt.Println("查询成功", stockReponse) }
-
-
运行
-
终端切换到项目目录下执行:
go run grpc_server.go
启动服务端 -
另启终端并切换到项目下的client目录下执行:
go run grpc_client.go
启动客户端,结果示例:user@C02FP58GML7H client % go run grpc_client.go 查询成功 prod_stock:100
-
也可以通过go build生成二进制的可执行文件来操作
-