GRPC学习笔记(三) go-grpc

【记录】go-grpc实战

前言

水了前两期博客之后终于迎来了实战环节,由于前一段一直抢不到3080,就生出了写个服务端脚本监控3080库存的想法,而在这个服务端程序中grpc的作用是把监控信息通知到我的手机上。可喜可贺的是还没有写完grpc的部分,我已经抢到了心心念念的3080了(耶)

配置Protobuf

grpc使用Protobuf作为传输数据格式,Protobuf是一种平台无关、语言无关、可扩展且轻便高效的序列化数据结构的协议,可以用于网络通信和数据存储。相比常用的JSON,proto的好处是高性能,代价是数据不可读性,以及配置起来比较麻烦。

1、首先去下载windows版本的protoc编译工具,并把bin路径配置到系统环境变量中,然后在命令行中输入 protoc 测试环境是否配置成功

https://github.com/protocolbuffers/protobuf/releases

2、安装protoc go 插件,安装成功后会在GOPATH目录下生成可执行的exe文件

go get -u github.com/golang/protobuf/protoc-gen-go

开始动手编码

1、定义protobuf文件

//proto版本
syntax="proto3";
//包名
package service;

message Empty{

}

//定义数据结构 repeated类似数组 可嵌套
message GoodsList{
    repeated Goods Goods = 1;
}

message Goods {
    string id = 1;
    string name =2;
    string state = 3;
}

//定义grpc服务接口 以及具体方法
service GetGoodsInfo{
    //单向流方法,服务端可以不断向客户端传输流式数据
    rpc Subscribe(Empty) returns (stream GoodsList);
}

2、编译protobuf文件,编写一个bash脚本,执行后生成go语言可访问的server.pb.go文件

protoc --go_out=plugins=grpc:. *.proto

3、编写服务端代码,首先要定义一个service结构体实现步骤1定义的接口

//GoodsService 空结构体 实现proto中的所有rpc
type GoodsService struct{}

// Subscribe 实现具体rpc 订阅商品到货信息
// Empty为方法的参数,stream是由proto中的 GetGoodsInfo+ Subscribe + Server拼成的,定义了流式结构的服务端rpc
func (*GoodsService) Subscribe(in *service.Empty, stream service.GetGoodsInfo_SubscribeServer) error {
    fmt.Println("recv rpc request Subscribe , ID = ", id)
    for {
        select {     
        //有缓冲的管道,一旦有商品到货信息流入,立马通知到手机客户端
        case goodsInfo := <-data.GoodsChannel:
            list := service.GoodsList{}
            ss := service.Goods{
                Id:    strconv.Itoa(goodsInfo.ID),
                Name:  goodsInfo.Name,
                State: goodsInfo.State,
            }
            list.Goods = append(list.Goods, &ss)

            //Send()方法发送数据到服务端,若返回错误信息则关闭此次服务
            err := stream.Send(&list)
            if err != nil {
                fmt.Println("recv disconnect Send")
                return err
            }
        
        //等待客户端channel关闭,服务端关闭此次服务
        case <-stream.Context().Done():
            fmt.Println("recv disconnect Recv")
            return nil
        }
    }
}

4、开始运行grpc服务


//RunRPC 启动RPC服务
func RunRPC() error {
    //监听端口
    sock, err := net.Listen("tcp", ":8080")
    if err != nil {
        return err
    }
    //配置最大接受和发送数据大小
    var opitions = []grpc.ServerOption{
        grpc.MaxRecvMsgSize(math.MaxInt32),
        grpc.MaxSendMsgSize(math.MaxInt32),
    }
    s := grpc.NewServer(opitions...)

    myServer := &GoodsService{}

    //注册gprc服务
    service.RegisterGetGoodsInfoServer(s, myServer)
    if err != nil {
        return err
    }

    fmt.Println("Start GRPC Server v1.0 at Port 8080")
    if err := s.Serve(sock); err != nil {
        log.Fatalf("failed to serve : %v", err)
    }
    return nil
}

结语

至此一个可运行的grpc服务端已经编写完毕,我的思路是保持和客户端的长连接,直到客户端退出或掉线才会关闭grpc服务,其他时间则一直等待监听信息的到来。下一篇继续讲客户端gprc的编写,我们将在安卓手机上接受3080到货的消息。

Licensed under CC BY-NC-SA 4.0
加载中...
感谢Jimmy 隐私政策