Golang gRPC 使用

1、概念

一、gRPC默認使用protocol buffers,這是google開源的一套成熟的結構數據序列化機制(固然也可使用其餘數據格式如JSON),能夠用proto files建立gRPC服務,用protocol buffers消息類型來定義方法參數和返回類型。git

2、安裝

一、yum install autoconf automake libtool  (centos 系統)github

二、protocal buffer安裝golang

從 https://github.com/google/protobuf/releases下載安裝包,解壓,而後操做如下命令:編程

./autogen.sh
./configure
make
make install

最後設置環境變量便可:export LD_LIBRARY_PATH=/usr/local/libjson

三、安裝 golang protobufcentos

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

四、安裝 gRPC-go服務器

go get google.golang.org/grpc

沒法下載的話去 https://github.com/grpc/grpc-go 下載數據結構

3、使用

一、編寫 proto 文件,helloworld.prototcp

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:是枚舉類型結構體
  • 數字:字段的標識符,不可重複
  • 數據類型: int3二、int6四、uint3二、uint6四、sint3二、sint6四、double、float、 string、bool、bytes、enum、message等等

二、使用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

三、服務器程序

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)
}

四、客戶端程序

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)
}
相關文章
相關標籤/搜索