zoukankan      html  css  js  c++  java
  • Golang gRPC 使用

    一、概念

    1、gRPC默认使用protocol buffers,这是google开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如JSON),可以用proto files创建gRPC服务,用protocol buffers消息类型来定义方法参数和返回类型。

    二、安装

    1、yum install autoconf automake libtool  (centos 系统)

    2、protocal buffer安装

    从 https://github.com/google/protobuf/releases下载安装包,解压,然后操作以下命令:

    ./autogen.sh
    ./configure
    make
    make install

    最后设置环境变量即可:export LD_LIBRARY_PATH=/usr/local/lib

    3、安装 golang protobuf

    go get -u github.com/golang/protobuf/proto // golang protobuf 库
    go get -u github.com/golang/protobuf/protoc-gen-go //protoc --go_out 工具

    4、安装 gRPC-go

    go get google.golang.org/grpc

    无法下载的话去 https://github.com/grpc/grpc-go 下载

    三、使用

    1、编写 proto 文件,helloworld.proto

    syntax = "proto3";
    
    option objc_class_prefix = "HLW";
    
    package helloworld;
    
    // The greeting service definition.
    service Greeter {
      // Sends a greeting
      rpc SayHello (HelloRequest) returns (HelloReply) {}
    }
    
    // The request message containing the user's name.
    message HelloRequest {
      string name = 1;
    }
    
    // The response message containing the greetings
    message HelloReply {
      string message = 1;
    }
    • syntax="proto3":指定protobuf的版本
    • package helloworld:声明一个报名,一般与文件目录名相同
    • import "xxx/xx.proto":导入其他的包,这样你就可以使用其他的包的数据结构
    • required、optional、repeated:表示该字段是否必须填充;required表示必须指定且只能指定一个;当optional表示可选,可指定也可不指定,但不可超过一个不指定值的时候会采用空值,如string类型的字段会用字符串表示;repeated表示可以重复,类似与编程语言中的list
    • message Author:在一个message体内定义一个message结构体
    • enum:是枚举类型结构体
    • 数字:字段的标识符,不可重复
    • 数据类型: int32、int64、uint32、uint64、sint32、sint64、double、float、 string、bool、bytes、enum、message等等

    2、使用protoc命令生成相关文件:

    protoc --go_out=plugins=grpc:. helloworld.proto
    ls
    helloworld.pb.go    helloworld.proto

    这里用了plugins选项,提供对grpc的支持,否则不会生成Service的接口,方便编写服务器和客户端程序

    helloworld.pb.go 文件如下:

      1 // Code generated by protoc-gen-go. DO NOT EDIT.
      2 // source: helloworld.proto
      3 
      4 package helloworld
      5 
      6 import (
      7     context "context"
      8     fmt "fmt"
      9     proto "github.com/golang/protobuf/proto"
     10     grpc "google.golang.org/grpc"
     11     math "math"
     12 )
     13 
     14 // Reference imports to suppress errors if they are not otherwise used.
     15 var _ = proto.Marshal
     16 var _ = fmt.Errorf
     17 var _ = math.Inf
     18 
     19 // This is a compile-time assertion to ensure that this generated file
     20 // is compatible with the proto package it is being compiled against.
     21 // A compilation error at this line likely means your copy of the
     22 // proto package needs to be updated.
     23 const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
     24 
     25 // The request message containing the user's name.
     26 type HelloRequest struct {
     27     Name                 string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
     28     XXX_NoUnkeyedLiteral struct{} `json:"-"`
     29     XXX_unrecognized     []byte   `json:"-"`
     30     XXX_sizecache        int32    `json:"-"`
     31 }
     32 
     33 func (m *HelloRequest) Reset()         { *m = HelloRequest{} }
     34 func (m *HelloRequest) String() string { return proto.CompactTextString(m) }
     35 func (*HelloRequest) ProtoMessage()    {}
     36 func (*HelloRequest) Descriptor() ([]byte, []int) {
     37     return fileDescriptor_17b8c58d586b62f2, []int{0}
     38 }
     39 
     40 func (m *HelloRequest) XXX_Unmarshal(b []byte) error {
     41     return xxx_messageInfo_HelloRequest.Unmarshal(m, b)
     42 }
     43 func (m *HelloRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
     44     return xxx_messageInfo_HelloRequest.Marshal(b, m, deterministic)
     45 }
     46 func (m *HelloRequest) XXX_Merge(src proto.Message) {
     47     xxx_messageInfo_HelloRequest.Merge(m, src)
     48 }
     49 func (m *HelloRequest) XXX_Size() int {
     50     return xxx_messageInfo_HelloRequest.Size(m)
     51 }
     52 func (m *HelloRequest) XXX_DiscardUnknown() {
     53     xxx_messageInfo_HelloRequest.DiscardUnknown(m)
     54 }
     55 
     56 var xxx_messageInfo_HelloRequest proto.InternalMessageInfo
     57 
     58 func (m *HelloRequest) GetName() string {
     59     if m != nil {
     60         return m.Name
     61     }
     62     return ""
     63 }
     64 
     65 // The response message containing the greetings
     66 type HelloReply struct {
     67     Message              string   `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
     68     XXX_NoUnkeyedLiteral struct{} `json:"-"`
     69     XXX_unrecognized     []byte   `json:"-"`
     70     XXX_sizecache        int32    `json:"-"`
     71 }
     72 
     73 func (m *HelloReply) Reset()         { *m = HelloReply{} }
     74 func (m *HelloReply) String() string { return proto.CompactTextString(m) }
     75 func (*HelloReply) ProtoMessage()    {}
     76 func (*HelloReply) Descriptor() ([]byte, []int) {
     77     return fileDescriptor_17b8c58d586b62f2, []int{1}
     78 }
     79 
     80 func (m *HelloReply) XXX_Unmarshal(b []byte) error {
     81     return xxx_messageInfo_HelloReply.Unmarshal(m, b)
     82 }
     83 func (m *HelloReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
     84     return xxx_messageInfo_HelloReply.Marshal(b, m, deterministic)
     85 }
     86 func (m *HelloReply) XXX_Merge(src proto.Message) {
     87     xxx_messageInfo_HelloReply.Merge(m, src)
     88 }
     89 func (m *HelloReply) XXX_Size() int {
     90     return xxx_messageInfo_HelloReply.Size(m)
     91 }
     92 func (m *HelloReply) XXX_DiscardUnknown() {
     93     xxx_messageInfo_HelloReply.DiscardUnknown(m)
     94 }
     95 
     96 var xxx_messageInfo_HelloReply proto.InternalMessageInfo
     97 
     98 func (m *HelloReply) GetMessage() string {
     99     if m != nil {
    100         return m.Message
    101     }
    102     return ""
    103 }
    104 
    105 func init() {
    106     proto.RegisterType((*HelloRequest)(nil), "helloworld.HelloRequest")
    107     proto.RegisterType((*HelloReply)(nil), "helloworld.HelloReply")
    108 }
    109 
    110 func init() { proto.RegisterFile("helloworld.proto", fileDescriptor_17b8c58d586b62f2) }
    111 
    112 var fileDescriptor_17b8c58d586b62f2 = []byte{
    113     // 149 bytes of a gzipped FileDescriptorProto
    114     0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9,
    115     0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x42, 0x88,
    116     0x28, 0x29, 0x71, 0xf1, 0x78, 0x80, 0x78, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x42,
    117     0x5c, 0x2c, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x60, 0xb6, 0x92,
    118     0x1a, 0x17, 0x17, 0x54, 0x4d, 0x41, 0x4e, 0xa5, 0x90, 0x04, 0x17, 0x7b, 0x6e, 0x6a, 0x71, 0x71,
    119     0x62, 0x3a, 0x4c, 0x11, 0x8c, 0x6b, 0xe4, 0xc9, 0xc5, 0xee, 0x5e, 0x94, 0x9a, 0x5a, 0x92, 0x5a,
    120     0x24, 0x64, 0xc7, 0xc5, 0x11, 0x9c, 0x58, 0x09, 0xd6, 0x25, 0x24, 0xa1, 0x87, 0xe4, 0x02, 0x64,
    121     0xcb, 0xa4, 0xc4, 0xb0, 0xc8, 0x14, 0xe4, 0x54, 0x2a, 0x31, 0x38, 0xb1, 0x2d, 0x62, 0x62, 0xf6,
    122     0xf0, 0x09, 0x4f, 0x62, 0x03, 0xbb, 0xd8, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xbe, 0xde, 0x1d,
    123     0x2e, 0xc5, 0x00, 0x00, 0x00,
    124 }
    125 
    126 // Reference imports to suppress errors if they are not otherwise used.
    127 var _ context.Context
    128 var _ grpc.ClientConn
    129 
    130 // This is a compile-time assertion to ensure that this generated file
    131 // is compatible with the grpc package it is being compiled against.
    132 const _ = grpc.SupportPackageIsVersion4
    133 
    134 // GreeterClient is the client API for Greeter service.
    135 //
    136 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
    137 type GreeterClient interface {
    138     // Sends a greeting
    139     SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
    140 }
    141 
    142 type greeterClient struct {
    143     cc *grpc.ClientConn
    144 }
    145 
    146 func NewGreeterClient(cc *grpc.ClientConn) GreeterClient {
    147     return &greeterClient{cc}
    148 }
    149 
    150 func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) {
    151     out := new(HelloReply)
    152     err := c.cc.Invoke(ctx, "/helloworld.Greeter/SayHello", in, out, opts...)
    153     if err != nil {
    154         return nil, err
    155     }
    156     return out, nil
    157 }
    158 
    159 // GreeterServer is the server API for Greeter service.
    160 type GreeterServer interface {
    161     // Sends a greeting
    162     SayHello(context.Context, *HelloRequest) (*HelloReply, error)
    163 }
    164 
    165 func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) {
    166     s.RegisterService(&_Greeter_serviceDesc, srv)
    167 }
    168 
    169 func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
    170     in := new(HelloRequest)
    171     if err := dec(in); err != nil {
    172         return nil, err
    173     }
    174     if interceptor == nil {
    175         return srv.(GreeterServer).SayHello(ctx, in)
    176     }
    177     info := &grpc.UnaryServerInfo{
    178         Server:     srv,
    179         FullMethod: "/helloworld.Greeter/SayHello",
    180     }
    181     handler := func(ctx context.Context, req interface{}) (interface{}, error) {
    182         return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest))
    183     }
    184     return interceptor(ctx, in, info, handler)
    185 }
    186 
    187 var _Greeter_serviceDesc = grpc.ServiceDesc{
    188     ServiceName: "helloworld.Greeter",
    189     HandlerType: (*GreeterServer)(nil),
    190     Methods: []grpc.MethodDesc{
    191         {
    192             MethodName: "SayHello",
    193             Handler:    _Greeter_SayHello_Handler,
    194         },
    195     },
    196     Streams:  []grpc.StreamDesc{},
    197     Metadata: "helloworld.proto",
    198 }
    View Code

    3、服务器程序

    package main
    
    import (
        "log"
        "net"
    
        pb "test_grpc/helloworld"
        "google.golang.org/grpc"
        "golang.org/x/net/context"
    )
    
    const (
        PORT = ":50001"
    )
    
    type server struct {}
    
    func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
        log.Println("request: ", in.Name)
        return &pb.HelloReply{Message: "Hello " + in.Name}, nil
    }
    
    func main() {
        lis, err := net.Listen("tcp", PORT)
    
        if err != nil {
            log.Fatalf("failed to listen: %v", err)
        }
    
        s := grpc.NewServer()
        pb.RegisterGreeterServer(s, &server{})
        log.Println("rpc服务已经开启")
        s.Serve(lis)
    }

    4、客户端程序

    package main
    
    import (
        "log"
        "os"
    
        pb "test_grpc/helloworld"
        "golang.org/x/net/context"
        "google.golang.org/grpc"
    )
    
    const (
        address = "localhost:50001"
    )
    
    func main() {
        conn, err := grpc.Dial(address, grpc.WithInsecure())
    
        if err != nil {
            log.Fatalf("did not connect: %v", err)
        }
    
        defer conn.Close()
    
        c := pb.NewGreeterClient(conn)
    
        name := "lin"
        if len(os.Args) > 1 {
            name = os.Args[1]
        }
    
        r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})
    
        if err != nil {
            log.Fatalf("could not greet: %v", err)
        }
    
        log.Println(r.Message)
    }
  • 相关阅读:
    【python】 time模块和datetime模块详解 【转】
    【python 】装饰器 (多个参数的函数,带参数的装饰器)【转】
    从测试角度对测试驱动开发的思考【转】
    mysql性能优化-慢查询分析、优化索引和配置【转】
    【python 】Requests 库学习笔记
    二本院校计算机专业考研上岸985
    mysql创建触发器
    pat 1134 Vertex Cover (25分) 超时问题
    数据库三级封锁协议简述
    pat 1139 First Contact (30分) 题目详解
  • 原文地址:https://www.cnblogs.com/linguoguo/p/10138715.html
Copyright © 2011-2022 走看看