概念图
grpc使用
安装
按照grpc官方文档 https://grpc.io/docs/languages/go/quickstart/
来运行
$ protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
helloworld/helloworld.proto
This will regenerate the helloworld/helloworld.pb.go
and helloworld/helloworld_grpc.pb.go
files, which contain:
Code for populating, serializing, and retrieving HelloRequest and HelloReply message types.
Generated client and server code
注:source_relative 会直接在本文件夹生成,而且不同于过往版本只生成一个pb.go
在prot文件夹指定
// name 表示生成的go文件所属的报名
option go_package = "../service";
然后将source_relative换成import即可
eg:
分布图:
D:\WORK\goCode\src\grpc_study\ms-proto\pbfile>protoc
--go_out=. --go_opt=paths=import
--go-grpc_out=. --go-grpc_opt=paths=import
./product.proto
注:./product.proto
为目标proto所处地址
eg
server
以product业务为例
product.proto
//指定的当前proto语法的版本,有2和3
syntax = "proto3";
//option go_package = "path;name" ;path表示生成的go文件的存放地址,会自动生成目录的
// name 表示生成的go文件所属的报名
option go_package = "../service";
//指定等会文件生成出来的package
package service;
//定义request model
message ProductRequest{
int32 prod_id = 1; //1代表顺序
}
//定义response model
message ProductResponse{
int32 pro_stock = 1; //1代表顺序
}
//定义服务主体
service ProdService{
//定义方法
rpc GetProductStock(ProductRequest) returns(ProductResponse);
}
product.go
在这个函数中写自己的业务逻辑,函数名为proto中所引用的函数名
package service
import (
"context"
"errors"
"fmt"
"time"
)
var ProductService = &productService{}
type productService struct {
}
func (p *productService) mustEmbedUnimplementedProdServiceServer() {
panic(any("implement me"))
}
func (p *productService) GetProductStock(context context.Context, request *ProductRequest) (*ProductResponse, error) {
time.Sleep(2*time.Second)
select {
case <-context.Done():
fmt.Println("server product done")
return &ProductResponse{ProStock: 0}, errors.New("time out")
default:
//实现具体的业务逻辑
stock := p.GetStockById(request.ProdId)
fmt.Println("success")
return &ProductResponse{ProStock: stock}, nil
}
}
func (p *productService) GetStockById(id int32) int32 {
return id
}
grpc_server.go
package main
import (
"fmt"
"google.golang.org/grpc"
"grpc_study/ms-proto/service"
"log"
"net"
)
func main() {
rpcServer := grpc.NewServer()
service.RegisterProdServiceServer(rpcServer,service.ProductService)
listener,err := net.Listen("tcp",":8002")
if err != nil{
log.Fatalln("启动监听出错",err)
}
err = rpcServer.Serve(listener)
if err != nil{
log.Fatalln("启动服务出错:",err)
}
fmt.Println("启动grpc服务端成功")
}
client
server端引入grpc server的proto文件并且创建后,可以直接调用函数并支持传入ctx来传达超时和取消
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"grpc_study/ms-proto/service"
"log"
"time"
)
func main() {
conn,err := grpc.Dial(":8002",grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil{
log.Fatal("服务端出错,连接失败",err)
}
defer conn.Close()
prodClient := service.NewProdServiceClient(conn)
request := &service.ProductRequest{
ProdId: 123,
}
ctx := context.Background()
proCtx,cancel := context.WithTimeout(ctx,3*time.Second)
stockResponse,err := prodClient.GetProductStock(proCtx,request)
if err != nil{
log.Fatal("查询库存出错,",err)
}
defer cancel()
fmt.Println("查询成功",stockResponse.ProStock)
fmt.Println(stockResponse)
}