一、概念
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下载安装包,解压,然后操作以下命令:
1./autogen.sh 2./configure 3make 4make install
最后设置环境变量即可:export LD_LIBRARY_PATH=/usr/local/lib

3、安装 golang protobuf
1go get -u github.com/golang/protobuf/proto // golang protobuf 库 2go 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
1syntax = "proto3"; 2 3option objc_class_prefix = "HLW"; 4 5package helloworld; 6 7// The greeting service definition. 8service Greeter { 9 // Sends a greeting 10 rpc SayHello (HelloRequest) returns (HelloReply) {} 11} 12 13// The request message containing the user's name. 14message HelloRequest { 15 string name = 1; 16} 17 18// The response message containing the greetings 19message HelloReply { 20 string message = 1; 21}
- 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命令生成相关文件:
1protoc --go_out=plugins=grpc:. helloworld.proto 2ls 3helloworld.pb.go helloworld.proto
这里用了plugins选项,提供对grpc的支持,否则不会生成Service的接口,方便编写服务器和客户端程序
helloworld.pb.go 文件如下:

1 1 // Code generated by protoc-gen-go. DO NOT EDIT. 2 2 // source: helloworld.proto 3 3 4 4 package helloworld 5 5 6 6 import ( 7 7 context "context" 8 8 fmt "fmt" 9 9 proto "github.com/golang/protobuf/proto" 10 10 grpc "google.golang.org/grpc" 11 11 math "math" 12 12 ) 13 13 14 14 // Reference imports to suppress errors if they are not otherwise used. 15 15 var _ = proto.Marshal 16 16 var _ = fmt.Errorf 17 17 var _ = math.Inf 18 18 19 19 // This is a compile-time assertion to ensure that this generated file 20 20 // is compatible with the proto package it is being compiled against. 21 21 // A compilation error at this line likely means your copy of the 22 22 // proto package needs to be updated. 23 23 const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 24 24 25 25 // The request message containing the user's name. 26 26 type HelloRequest struct { 27 27 Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` 28 28 XXX_NoUnkeyedLiteral struct{} `json:"-"` 29 29 XXX_unrecognized []byte `json:"-"` 30 30 XXX_sizecache int32 `json:"-"` 31 31 } 32 32 33 33 func (m *HelloRequest) Reset() { *m = HelloRequest{} } 34 34 func (m *HelloRequest) String() string { return proto.CompactTextString(m) } 35 35 func (*HelloRequest) ProtoMessage() {} 36 36 func (*HelloRequest) Descriptor() ([]byte, []int) { 37 37 return fileDescriptor_17b8c58d586b62f2, []int{0} 38 38 } 39 39 40 40 func (m *HelloRequest) XXX_Unmarshal(b []byte) error { 41 41 return xxx_messageInfo_HelloRequest.Unmarshal(m, b) 42 42 } 43 43 func (m *HelloRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 44 44 return xxx_messageInfo_HelloRequest.Marshal(b, m, deterministic) 45 45 } 46 46 func (m *HelloRequest) XXX_Merge(src proto.Message) { 47 47 xxx_messageInfo_HelloRequest.Merge(m, src) 48 48 } 49 49 func (m *HelloRequest) XXX_Size() int { 50 50 return xxx_messageInfo_HelloRequest.Size(m) 51 51 } 52 52 func (m *HelloRequest) XXX_DiscardUnknown() { 53 53 xxx_messageInfo_HelloRequest.DiscardUnknown(m) 54 54 } 55 55 56 56 var xxx_messageInfo_HelloRequest proto.InternalMessageInfo 57 57 58 58 func (m *HelloRequest) GetName() string { 59 59 if m != nil { 60 60 return m.Name 61 61 } 62 62 return "" 63 63 } 64 64 65 65 // The response message containing the greetings 66 66 type HelloReply struct { 67 67 Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 68 68 XXX_NoUnkeyedLiteral struct{} `json:"-"` 69 69 XXX_unrecognized []byte `json:"-"` 70 70 XXX_sizecache int32 `json:"-"` 71 71 } 72 72 73 73 func (m *HelloReply) Reset() { *m = HelloReply{} } 74 74 func (m *HelloReply) String() string { return proto.CompactTextString(m) } 75 75 func (*HelloReply) ProtoMessage() {} 76 76 func (*HelloReply) Descriptor() ([]byte, []int) { 77 77 return fileDescriptor_17b8c58d586b62f2, []int{1} 78 78 } 79 79 80 80 func (m *HelloReply) XXX_Unmarshal(b []byte) error { 81 81 return xxx_messageInfo_HelloReply.Unmarshal(m, b) 82 82 } 83 83 func (m *HelloReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 84 84 return xxx_messageInfo_HelloReply.Marshal(b, m, deterministic) 85 85 } 86 86 func (m *HelloReply) XXX_Merge(src proto.Message) { 87 87 xxx_messageInfo_HelloReply.Merge(m, src) 88 88 } 89 89 func (m *HelloReply) XXX_Size() int { 90 90 return xxx_messageInfo_HelloReply.Size(m) 91 91 } 92 92 func (m *HelloReply) XXX_DiscardUnknown() { 93 93 xxx_messageInfo_HelloReply.DiscardUnknown(m) 94 94 } 95 95 96 96 var xxx_messageInfo_HelloReply proto.InternalMessageInfo 97 97 98 98 func (m *HelloReply) GetMessage() string { 99 99 if m != nil { 100100 return m.Message 101101 } 102102 return "" 103103 } 104104 105105 func init() { 106106 proto.RegisterType((*HelloRequest)(nil), "helloworld.HelloRequest") 107107 proto.RegisterType((*HelloReply)(nil), "helloworld.HelloReply") 108108 } 109109 110110 func init() { proto.RegisterFile("helloworld.proto", fileDescriptor_17b8c58d586b62f2) } 111111 112112 var fileDescriptor_17b8c58d586b62f2 = []byte{ 113113 // 149 bytes of a gzipped FileDescriptorProto 114114 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9, 115115 0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x42, 0x88, 116116 0x28, 0x29, 0x71, 0xf1, 0x78, 0x80, 0x78, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x42, 117117 0x5c, 0x2c, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x60, 0xb6, 0x92, 118118 0x1a, 0x17, 0x17, 0x54, 0x4d, 0x41, 0x4e, 0xa5, 0x90, 0x04, 0x17, 0x7b, 0x6e, 0x6a, 0x71, 0x71, 119119 0x62, 0x3a, 0x4c, 0x11, 0x8c, 0x6b, 0xe4, 0xc9, 0xc5, 0xee, 0x5e, 0x94, 0x9a, 0x5a, 0x92, 0x5a, 120120 0x24, 0x64, 0xc7, 0xc5, 0x11, 0x9c, 0x58, 0x09, 0xd6, 0x25, 0x24, 0xa1, 0x87, 0xe4, 0x02, 0x64, 121121 0xcb, 0xa4, 0xc4, 0xb0, 0xc8, 0x14, 0xe4, 0x54, 0x2a, 0x31, 0x38, 0xb1, 0x2d, 0x62, 0x62, 0xf6, 122122 0xf0, 0x09, 0x4f, 0x62, 0x03, 0xbb, 0xd8, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xbe, 0xde, 0x1d, 123123 0x2e, 0xc5, 0x00, 0x00, 0x00, 124124 } 125125 126126 // Reference imports to suppress errors if they are not otherwise used. 127127 var _ context.Context 128128 var _ grpc.ClientConn 129129 130130 // This is a compile-time assertion to ensure that this generated file 131131 // is compatible with the grpc package it is being compiled against. 132132 const _ = grpc.SupportPackageIsVersion4 133133 134134 // GreeterClient is the client API for Greeter service. 135135 // 136136 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 137137 type GreeterClient interface { 138138 // Sends a greeting 139139 SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) 140140 } 141141 142142 type greeterClient struct { 143143 cc *grpc.ClientConn 144144 } 145145 146146 func NewGreeterClient(cc *grpc.ClientConn) GreeterClient { 147147 return &greeterClient{cc} 148148 } 149149 150150 func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { 151151 out := new(HelloReply) 152152 err := c.cc.Invoke(ctx, "/helloworld.Greeter/SayHello", in, out, opts...) 153153 if err != nil { 154154 return nil, err 155155 } 156156 return out, nil 157157 } 158158 159159 // GreeterServer is the server API for Greeter service. 160160 type GreeterServer interface { 161161 // Sends a greeting 162162 SayHello(context.Context, *HelloRequest) (*HelloReply, error) 163163 } 164164 165165 func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) { 166166 s.RegisterService(&_Greeter_serviceDesc, srv) 167167 } 168168 169169 func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 170170 in := new(HelloRequest) 171171 if err := dec(in); err != nil { 172172 return nil, err 173173 } 174174 if interceptor == nil { 175175 return srv.(GreeterServer).SayHello(ctx, in) 176176 } 177177 info := &grpc.UnaryServerInfo{ 178178 Server: srv, 179179 FullMethod: "/helloworld.Greeter/SayHello", 180180 } 181181 handler := func(ctx context.Context, req interface{}) (interface{}, error) { 182182 return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) 183183 } 184184 return interceptor(ctx, in, info, handler) 185185 } 186186 187187 var _Greeter_serviceDesc = grpc.ServiceDesc{ 188188 ServiceName: "helloworld.Greeter", 189189 HandlerType: (*GreeterServer)(nil), 190190 Methods: []grpc.MethodDesc{ 191191 { 192192 MethodName: "SayHello", 193193 Handler: _Greeter_SayHello_Handler, 194194 }, 195195 }, 196196 Streams: []grpc.StreamDesc{}, 197197 Metadata: "helloworld.proto", 198198 }
View Code
3、服务器程序
1package main 2 3import ( 4 "log" 5 "net" 6 7 pb "test_grpc/helloworld" 8 "google.golang.org/grpc" 9 "golang.org/x/net/context" 10) 11 12const ( 13 PORT = ":50001" 14) 15 16type server struct {} 17 18func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { 19 log.Println("request: ", in.Name) 20 return &pb.HelloReply{Message: "Hello " + in.Name}, nil 21} 22 23func main() { 24 lis, err := net.Listen("tcp", PORT) 25 26 if err != nil { 27 log.Fatalf("failed to listen: %v", err) 28 } 29 30 s := grpc.NewServer() 31 pb.RegisterGreeterServer(s, &server{}) 32 log.Println("rpc服务已经开启") 33 s.Serve(lis) 34}
4、客户端程序
1package main 2 3import ( 4 "log" 5 "os" 6 7 pb "test_grpc/helloworld" 8 "golang.org/x/net/context" 9 "google.golang.org/grpc" 10) 11 12const ( 13 address = "localhost:50001" 14) 15 16func main() { 17 conn, err := grpc.Dial(address, grpc.WithInsecure()) 18 19 if err != nil { 20 log.Fatalf("did not connect: %v", err) 21 } 22 23 defer conn.Close() 24 25 c := pb.NewGreeterClient(conn) 26 27 name := "lin" 28 if len(os.Args) > 1 { 29 name = os.Args[1] 30 } 31 32 r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name}) 33 34 if err != nil { 35 log.Fatalf("could not greet: %v", err) 36 } 37 38 log.Println(r.Message) 39}