gRPC 入门(一)
2022/1/11 6:05:26
本文主要是介绍gRPC 入门(一),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
在学习 gRPC
之前,先学习 protobufu
协议,简单的来理解,我们可以使用他来定义 消息
和 服务
。然后你只需要实现服务即可,剩下的东西,gRPC
会帮你自动完成。
protobufu 协议
protobuf
协议,可以适用于十几种开发语言,并且允许你使用同一种框架,每秒支持百万级以上的 RPC 调用
mac 中安装 gRPC 需要的环境
方法和 linux
中安装 gRPC
基本一样
cd ~/software/protobuf #创建一个 software 文件,当时你也可以按照自己的习惯,放到 usr 文件夹中。 wget https://github.com/protocolbuffers/protobuf/releases/download/v3.12.0/protoc-3.12.0-osx-x86_64.zip # 在下载 grpc 的安装包 unzip protoc-3.12.0-osx-x86_64.zip # 解压安装包 mv bin/protoc /usr/local/protoc # 通过将 bin 文件放到 protoc 中的方法,将 protoc 命令添加到 path 中
查看 protoc
的版本信息
protoc --version # 输出 libprotoc 3.7.1
上面安装步骤完成以后,只是安装了 protobuf
的基础功能包。我们想要使用 go
语言中的 gprc
功能,还需要安装 grpc
的包。
在任意的有mod 的文件下,执行如下命令
go get google.golang.org/grpc
如果想对此包做更多理解,可以查询 gPRC 的中文官方文档: http://doc.oschina.net/grpc?t=60133
一个小 demo
通过 grpc
协议,定义一个客户端,实现以下两个功能,并使用 grpc 的 client 端来调用
-
添加产品
-
根据产品 id 来查询产品信息
定义一个能添加产品和查询产品的 protobuf 文件
syntax = "proto3"; package ecommerce; option go_package="./econFileName"; // 文件名和包名,此两个文件保持一致 service ProductInfo { rpc addProduct(Product) returns (ProductID); rpc getProduct(ProductID) returns (Product); } message Product { string id = 1; string name = 2; string description = 3; float price = 4; } message ProductID { string value = 1; }
在声明 protobuf 的文件夹下,执行如下命令,会自动生成对应的 go
文件,切记,此文件只能查看,不可更改
protoc --go_out=plugins=grpc:. *.proto
服务端
1. 找到自动生成的 go 文件中 grpc 服务端的接口
打开自动生成的 go 文件,可以看到 server
接口。注意和客户端的接口区分,此处是 Server 结尾的
2. 重载此接口
根据 go 语言非入侵的接口实现方式,声明一个结构体,只要实现了某接口的所有方法,那么他就实现了这个接口
type server struct { products []*pb.Product } func (s *server) AddProduct(ctx context.Context, product *pb.Product) (*pb.ProductID, error) { product.Id = uuid.New().String() s.products = append(s.products, product) return &pb.ProductID{ Value: product.Id, }, status.New(codes.OK, "").Err() } func (s *server) GetProduct(ctx context.Context, proId *pb.ProductID) (*pb.Product, error) { for _, prod := range s.products { if prod.Id == proId.Value { return prod, status.New(codes.OK, "").Err() } } return nil, status.Errorf(codes.NotFound, "product not exist", proId.Value) }
3.启动服务,监听 5001 端口
package main import ( "context" "fmt" "net" pb "zhao/grpc/pb/econFileName" "github.com/google/uuid" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) const ( port = ":5001" ) type server struct { products []*pb.Product } func (s *server) AddProduct(ctx context.Context, product *pb.Product) (*pb.ProductID, error) { product.Id = uuid.New().String() s.products = append(s.products, product) return &pb.ProductID{ Value: product.Id, }, status.New(codes.OK, "").Err() } func (s *server) GetProduct(ctx context.Context, proId *pb.ProductID) (*pb.Product, error) { for _, prod := range s.products { if prod.Id == proId.Value { return prod, status.New(codes.OK, "").Err() } } return nil, status.Errorf(codes.NotFound, "product not exist", proId.Value) } func main() { lis, err := net.Listen("tcp", port) if err != nil { panic(err) } fmt.Printf("net service is starting at :%s\n", port) s := grpc.NewServer() pb.RegisterProductInfoServer(s, &server{}) if err = s.Serve(lis); err != nil { panic(fmt.Sprintf("tpc web service port:【%s】 launch fail %v", port, err)) } }
-
注意,grpc 方法的传入和传出,都是结构体,即使是
productId
这种简单的 string 类型的形参,也应该使用自动生成的proto.go
文件中定义好的结构体 -
grpc 的方法调用中,也会有状态码,使用
google.golang.org/grpc/codes
包引用
完整代码如下
package main import ( "context" "fmt" "time" pb "zhao/grpc/pb/econFileName" "google.golang.org/grpc" ) const ( address = "localhost:5001" ) func main() { conn, err := grpc.Dial(address, grpc.WithInsecure()) if err != nil { fmt.Printf("connect grpc service fail at %s", address) } defer conn.Close() client := pb.NewProductInfoClient(conn) product1 := pb.Product{ Name: "Apple iPhone 11", Description: "Meet Apple iPhone 11. All-new dual-camera system with Ultra Wide and Night mode.", Price: float32(699.00), } ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() // 添加产品 id, err := client.AddProduct(ctx, &product1) if err != nil { fmt.Printf("client productid [%s] add product fail err: %v\n", product1.Id, err) } fmt.Printf("grpc req response product id [%s]\n", id.Value) // 查询产品 req_id := pb.ProductID{Value: id.Value} res, err := client.GetProduct(ctx, &req_id) if err != nil { fmt.Printf("client get product fail id is %s\n", req_id.Value) } fmt.Printf("get product successful %s\n", res.String()) }
客户端
1. 声明连接使用的字符串
conn, err := grpc.Dial("localhost:5001", grpc.WithInsecure())
2.使用自动生成的 go 文件中的方法,创建 productInfo 对应的是实例
client := pb.NewProductInfoClient(conn)
3. 此时,你就可以拿着这个客户端实例,像本地方法调用一样使用远端方法了
res, err := client.GetProduct(ctx, &req_id)
完整代码如下
package main import ( "context" "fmt" "time" pb "zhao/grpc/pb/econFileName" "google.golang.org/grpc" ) const ( address = "localhost:5001" ) func main() { conn, err := grpc.Dial("localhost:5001", grpc.WithInsecure()) if err != nil { fmt.Printf("connect grpc service fail at %s", address) } defer conn.Close() client := pb.NewProductInfoClient(conn) product1 := pb.Product{ Name: "Apple iPhone 11", Description: "Meet Apple iPhone 11. All-new dual-camera system with Ultra Wide and Night mode.", Price: float32(699.00), } ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() // 添加产品 id, err := client.AddProduct(ctx, &product1) if err != nil { fmt.Printf("client productid [%s] add product fail err: %v\n", product1.Id, err) } fmt.Printf("grpc req response product id [%s]\n", id.Value) // 查询产品 req_id := pb.ProductID{Value: id.Value} res, err := client.GetProduct(ctx, &req_id) if err != nil { fmt.Printf("client get product fail id is %s\n", req_id.Value) } fmt.Printf("get product successful %s\n", res.String()) }
这篇关于gRPC 入门(一)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-15Typescript 类型教程:轻松入门与实践指南
- 2024-11-15AntDesign-icons项目实战:新手入门教程
- 2024-11-14用Scratch编写语言模型:爪爪(Clawed)式简易教程
- 2024-11-14用大型语言模型在Amazon Bedrock上分类Jira工单
- 2024-11-14从数据到行动:亚马逊Bedrock代理如何自动化复杂工作流
- 2024-11-14Databricks与优化后的Snowflake性能大比拼
- 2024-11-14亚马逊 Inspector 解析:提升您的 AWS 负载安全的利器
- 2024-11-14揭秘VS Code for Web - Azure:轻松开发云端应用的新利器
- 2024-11-14揭秘指南:如何让Databricks中的数据为最终用户所用
- 2024-11-14OpenTelemetry扩展进入CI/CD可观测性领域