Go语言gRPC服务

gRPC是一个有google推出的、高性能、开源、通用的远程过程调用(RPC)框架。

image

基本开发流程:

  • 在一个 .proto 文件内定义服务
  • 用 protocol buffer 编译器生成服务器和客户端代码
  • 使用 gRPC 的 Go API 为你的服务实现一个简单的客户端和服务器

定义服务

使用 protocol buffers 去定义 gRPC service 和方法 request 以及 response 的类型。

syntax = "proto3";

package device;

service Device {
    rpc PostProperty(PropertyReq) returns (CommonRsp) {}
}

message PropertyReq{
    string Attr = 1;
    string Value = 2;
}

message CommonRsp{
    int32 Code = 1;
    string ErrMsg = 2;
}

生成客户端和服务器端代码

通过 protocol buffer 的编译器 protoc来生成

go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
go get -u google.golang.org/grpc
protoc --go_out=plugins=grpc:. *.proto

运行命令后在当前目录中生成下面的文件:

  • device.pb.go

创建服务器

服务工作有两个部分:

  • 实现我们服务定义的生成的服务接口:做我们的服务的实际的“工作”。
  • 运行一个 gRPC 服务器,监听来自客户端的请求并返回服务的响应。

启动服务

package device

import (
    "context"
    "google.golang.org/grpc"
)

type Server struct {
    UnimplementedDeviceServer
} 

func (this *Server) PostProperty(ctx context.Context, req *PropertyReq) (*CommonRsp, error) {

    if req.Attr == "" {
        return &CommonRsp{Code: 500, ErrMsg: "Invalid Attr"}, nil
    }

    // do something

    return &CommonRsp{Code: 200, ErrMsg: "OK"}, nil;
}

func RegeisterService(server *grpc.Server) {
    RegisterDeviceServer(server, &Server{})
}

服务实现

package device

import (
    "context"
    "google.golang.org/grpc"
)

type Server struct {
    UnimplementedDeviceServer
} 

func (this *Server) PostProperty(ctx context.Context, req *PropertyReq) (*CommonRsp, error) {

    if req.Attr == "" {
        return &CommonRsp{Code: 500, ErrMsg: "Invalid Attr"}, nil
    }

    // do something

    return &CommonRsp{Code: 200, ErrMsg: "OK"}, nil;
}

func RegeisterService(server *grpc.Server) {
    RegisterDeviceServer(server, &Server{})
}

创建客户端

package main

import (
    "context"
    "log" 
    "time"

    "www.github.com/oulp/go/device"
    "google.golang.org/grpc" 
)

const (
    address  = "localhost:50051" 
)

func main() {

    // 建立连接
    conn, err := grpc.Dial(address, grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    } 
    defer conn.Close()

    // 超时设置
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()

    // 调用服务
    client := device.NewDeviceClient(conn)
    rsp, err := client.PostProperty(ctx, &device.PropertyReq{Attr: "A01", Value: "100"})
    if err != nil {
        log.Fatalf("could not: %v", err)
    }
    log.Printf("Rsp: %s %s", rsp.GetCode(), rsp.GetErrMsg())
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容