go-kit实践之1:go-kit 与 grpc 结合开发微服务(go-kit endpoint的使用)

释放双眼,带上耳机,听听看~!

go-kit 是一个微服务的开发工具集,微服务系统中的大多数常见问题,因此,使用者可以将精力集中在业务逻辑上。

grpc缺乏服务治理的功能,我们可以通过go-kit结合grpc来实现我们的完整需求。go-kit抽象的endpoint设计让我们可以很容易包装其它微服务框架使用的协议。
endpoint为Servers和Clients提供了基于RPC方法的构建模块。

先来看看endpoint源码:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
1package endpoint
2
3import (
4   "context"
5)
6
7// Endpoint is the fundamental building block of servers and clients.
8// It represents a single RPC method.
9type Endpoint func(ctx context.Context, request interface{}) (response interface{}, err error)
10
11// Nop is an endpoint that does nothing and returns a nil error.
12// Useful for tests.
13func Nop(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil }
14
15// Middleware is a chainable behavior modifier for endpoints.
16type Middleware func(Endpoint) Endpoint
17
18// Chain is a helper function for composing middlewares. Requests will
19// traverse them in the order they're declared. That is, the first middleware
20// is treated as the outermost middleware.
21func Chain(outer Middleware, others ...Middleware) Middleware {
22  return func(next Endpoint) Endpoint {
23      for i := len(others) - 1; i >= 0; i-- { // reverse
24          next = others[i](next)
25      }
26      return outer(next)
27  }
28}
29
30// Failer may be implemented by Go kit response types that contain business
31// logic error details. If Failed returns a non-nil error, the Go kit transport
32// layer may interpret this as a business logic error, and may encode it
33// differently than a regular, successful response.
34//
35// It's not necessary for your response types to implement Failer, but it may
36// help for more sophisticated use cases. The addsvc example shows how Failer
37// should be used by a complete application.
38type Failer interface {
39  Failed() error
40}
41
42

go-kit提供以下功能:

1、Circuit breaker(熔断器)

2、Rate limiter(限流器)

3、Logging(日志)

4、Metrics(Prometheus统计)

5、Request tracing(请求跟踪)

6、Service discovery and load balancing(服务发现和负载均衡)

1、安装go-kit包


1
2
1git clone https://github.com/go-kit/kit.git
2

放入到对应的gopath目录下。

2、protobuf文件


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1syntax = "proto3";
2
3// 请求书详情的参数结构  book_id 32位整形
4message BookInfoParams {
5    int32 book_id = 1;
6}
7
8
9// 书详情信息的结构   book_name字符串类型
10message BookInfo {
11    int32 book_id = 1;
12    string  book_name = 2;
13}
14
15// 请求书列表的参数结构  page、limit   32位整形
16message BookListParams {
17    int32 page = 1;
18    int32 limit = 2;
19}
20
21
22// 书列表的结构    BookInfo结构数组
23message BookList {
24    repeated BookInfo book_list = 1;
25}
26// 定义 获取书详情  和 书列表服务   入参出参分别为上面所定义的结构
27service BookService {
28    rpc GetBookInfo (BookInfoParams) returns (BookInfo) {}
29    rpc GetBookList (BookListParams) returns (BookList) {}
30}
31

生成对应的go语言代码文件:protoc –go_out=plugins=grpc:. book.proto  (其中:protobuf文件名为:book.proto),生成的代码如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
1// Code generated by protoc-gen-go. DO NOT EDIT.
2// source: book.proto
3
4package book
5
6import (
7   context "context"
8   fmt "fmt"
9   proto "github.com/golang/protobuf/proto"
10  grpc "google.golang.org/grpc"
11  codes "google.golang.org/grpc/codes"
12  status "google.golang.org/grpc/status"
13  math "math"
14)
15
16// Reference imports to suppress errors if they are not otherwise used.
17var _ = proto.Marshal
18var _ = fmt.Errorf
19var _ = math.Inf
20
21// This is a compile-time assertion to ensure that this generated file
22// is compatible with the proto package it is being compiled against.
23// A compilation error at this line likely means your copy of the
24// proto package needs to be updated.
25const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
26
27// 请求书详情的参数结构  book_id 32位整形
28type BookInfoParams struct {
29  BookId               int32    `protobuf:"varint,1,opt,name=book_id,json=bookId,proto3" json:"book_id,omitempty"`
30  XXX_NoUnkeyedLiteral struct{} `json:"-"`
31  XXX_unrecognized     []byte   `json:"-"`
32  XXX_sizecache        int32    `json:"-"`
33}
34
35func (m *BookInfoParams) Reset()         { *m = BookInfoParams{} }
36func (m *BookInfoParams) String() string { return proto.CompactTextString(m) }
37func (*BookInfoParams) ProtoMessage()    {}
38func (*BookInfoParams) Descriptor() ([]byte, []int) {
39  return fileDescriptor_1e89d0eaa98dc5d8, []int{0}
40}
41
42func (m *BookInfoParams) XXX_Unmarshal(b []byte) error {
43  return xxx_messageInfo_BookInfoParams.Unmarshal(m, b)
44}
45func (m *BookInfoParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
46  return xxx_messageInfo_BookInfoParams.Marshal(b, m, deterministic)
47}
48func (m *BookInfoParams) XXX_Merge(src proto.Message) {
49  xxx_messageInfo_BookInfoParams.Merge(m, src)
50}
51func (m *BookInfoParams) XXX_Size() int {
52  return xxx_messageInfo_BookInfoParams.Size(m)
53}
54func (m *BookInfoParams) XXX_DiscardUnknown() {
55  xxx_messageInfo_BookInfoParams.DiscardUnknown(m)
56}
57
58var xxx_messageInfo_BookInfoParams proto.InternalMessageInfo
59
60func (m *BookInfoParams) GetBookId() int32 {
61  if m != nil {
62      return m.BookId
63  }
64  return 0
65}
66
67// 书详情信息的结构   book_name字符串类型
68type BookInfo struct {
69  BookId               int32    `protobuf:"varint,1,opt,name=book_id,json=bookId,proto3" json:"book_id,omitempty"`
70  BookName             string   `protobuf:"bytes,2,opt,name=book_name,json=bookName,proto3" json:"book_name,omitempty"`
71  XXX_NoUnkeyedLiteral struct{} `json:"-"`
72  XXX_unrecognized     []byte   `json:"-"`
73  XXX_sizecache        int32    `json:"-"`
74}
75
76func (m *BookInfo) Reset()         { *m = BookInfo{} }
77func (m *BookInfo) String() string { return proto.CompactTextString(m) }
78func (*BookInfo) ProtoMessage()    {}
79func (*BookInfo) Descriptor() ([]byte, []int) {
80  return fileDescriptor_1e89d0eaa98dc5d8, []int{1}
81}
82
83func (m *BookInfo) XXX_Unmarshal(b []byte) error {
84  return xxx_messageInfo_BookInfo.Unmarshal(m, b)
85}
86func (m *BookInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
87  return xxx_messageInfo_BookInfo.Marshal(b, m, deterministic)
88}
89func (m *BookInfo) XXX_Merge(src proto.Message) {
90  xxx_messageInfo_BookInfo.Merge(m, src)
91}
92func (m *BookInfo) XXX_Size() int {
93  return xxx_messageInfo_BookInfo.Size(m)
94}
95func (m *BookInfo) XXX_DiscardUnknown() {
96  xxx_messageInfo_BookInfo.DiscardUnknown(m)
97}
98
99var xxx_messageInfo_BookInfo proto.InternalMessageInfo
100
101func (m *BookInfo) GetBookId() int32 {
102 if m != nil {
103     return m.BookId
104 }
105 return 0
106}
107
108func (m *BookInfo) GetBookName() string {
109 if m != nil {
110     return m.BookName
111 }
112 return ""
113}
114
115// 请求书列表的参数结构  page、limit   32位整形
116type BookListParams struct {
117 Page                 int32    `protobuf:"varint,1,opt,name=page,proto3" json:"page,omitempty"`
118 Limit                int32    `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"`
119 XXX_NoUnkeyedLiteral struct{} `json:"-"`
120 XXX_unrecognized     []byte   `json:"-"`
121 XXX_sizecache        int32    `json:"-"`
122}
123
124func (m *BookListParams) Reset()         { *m = BookListParams{} }
125func (m *BookListParams) String() string { return proto.CompactTextString(m) }
126func (*BookListParams) ProtoMessage()    {}
127func (*BookListParams) Descriptor() ([]byte, []int) {
128 return fileDescriptor_1e89d0eaa98dc5d8, []int{2}
129}
130
131func (m *BookListParams) XXX_Unmarshal(b []byte) error {
132 return xxx_messageInfo_BookListParams.Unmarshal(m, b)
133}
134func (m *BookListParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
135 return xxx_messageInfo_BookListParams.Marshal(b, m, deterministic)
136}
137func (m *BookListParams) XXX_Merge(src proto.Message) {
138 xxx_messageInfo_BookListParams.Merge(m, src)
139}
140func (m *BookListParams) XXX_Size() int {
141 return xxx_messageInfo_BookListParams.Size(m)
142}
143func (m *BookListParams) XXX_DiscardUnknown() {
144 xxx_messageInfo_BookListParams.DiscardUnknown(m)
145}
146
147var xxx_messageInfo_BookListParams proto.InternalMessageInfo
148
149func (m *BookListParams) GetPage() int32 {
150 if m != nil {
151     return m.Page
152 }
153 return 0
154}
155
156func (m *BookListParams) GetLimit() int32 {
157 if m != nil {
158     return m.Limit
159 }
160 return 0
161}
162
163// 书列表的结构    BookInfo结构数组
164type BookList struct {
165 BookList             []*BookInfo `protobuf:"bytes,1,rep,name=book_list,json=bookList,proto3" json:"book_list,omitempty"`
166 XXX_NoUnkeyedLiteral struct{}    `json:"-"`
167 XXX_unrecognized     []byte      `json:"-"`
168 XXX_sizecache        int32       `json:"-"`
169}
170
171func (m *BookList) Reset()         { *m = BookList{} }
172func (m *BookList) String() string { return proto.CompactTextString(m) }
173func (*BookList) ProtoMessage()    {}
174func (*BookList) Descriptor() ([]byte, []int) {
175 return fileDescriptor_1e89d0eaa98dc5d8, []int{3}
176}
177
178func (m *BookList) XXX_Unmarshal(b []byte) error {
179 return xxx_messageInfo_BookList.Unmarshal(m, b)
180}
181func (m *BookList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
182 return xxx_messageInfo_BookList.Marshal(b, m, deterministic)
183}
184func (m *BookList) XXX_Merge(src proto.Message) {
185 xxx_messageInfo_BookList.Merge(m, src)
186}
187func (m *BookList) XXX_Size() int {
188 return xxx_messageInfo_BookList.Size(m)
189}
190func (m *BookList) XXX_DiscardUnknown() {
191 xxx_messageInfo_BookList.DiscardUnknown(m)
192}
193
194var xxx_messageInfo_BookList proto.InternalMessageInfo
195
196func (m *BookList) GetBookList() []*BookInfo {
197 if m != nil {
198     return m.BookList
199 }
200 return nil
201}
202
203func init() {
204 proto.RegisterType((*BookInfoParams)(nil), "BookInfoParams")
205 proto.RegisterType((*BookInfo)(nil), "BookInfo")
206 proto.RegisterType((*BookListParams)(nil), "BookListParams")
207 proto.RegisterType((*BookList)(nil), "BookList")
208}
209
210func init() { proto.RegisterFile("book.proto", fileDescriptor_1e89d0eaa98dc5d8) }
211
212var fileDescriptor_1e89d0eaa98dc5d8 = []byte{
213 // 224 bytes of a gzipped FileDescriptorProto
214 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0xca, 0xcf, 0xcf,
215 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0xd2, 0xe4, 0xe2, 0x73, 0xca, 0xcf, 0xcf, 0xf6, 0xcc,
216 0x4b, 0xcb, 0x0f, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0x16, 0x12, 0xe7, 0x62, 0x07, 0xc9, 0xc7, 0x67,
217 0xa6, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0xb0, 0x06, 0xb1, 0x81, 0xb8, 0x9e, 0x29, 0x4a, 0x0e, 0x5c,
218 0x1c, 0x30, 0xa5, 0x38, 0x15, 0x09, 0x49, 0x73, 0x71, 0x82, 0x25, 0xf2, 0x12, 0x73, 0x53, 0x25,
219 0x98, 0x14, 0x18, 0x35, 0x38, 0x83, 0x38, 0x40, 0x02, 0x7e, 0x89, 0xb9, 0xa9, 0x4a, 0x56, 0x10,
220 0xcb, 0x7c, 0x32, 0x8b, 0x4b, 0xa0, 0x96, 0x09, 0x71, 0xb1, 0x14, 0x24, 0xa6, 0xa7, 0x42, 0x0d,
221 0x01, 0xb3, 0x85, 0x44, 0xb8, 0x58, 0x73, 0x32, 0x73, 0x33, 0x4b, 0xc0, 0xda, 0x59, 0x83, 0x20,
222 0x1c, 0x25, 0x23, 0x88, 0xed, 0x20, 0xbd, 0x42, 0x6a, 0x50, 0x4b, 0x72, 0x32, 0x8b, 0x4b, 0x24,
223 0x18, 0x15, 0x98, 0x35, 0xb8, 0x8d, 0x38, 0xf5, 0x60, 0x6e, 0x83, 0xd8, 0x07, 0x52, 0x67, 0x94,
224 0xce, 0xc5, 0x0d, 0x12, 0x0d, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x15, 0xd2, 0xe6, 0xe2, 0x76,
225 0x4f, 0x2d, 0x81, 0xfb, 0x81, 0x5f, 0x0f, 0xd5, 0xe7, 0x52, 0x08, 0x33, 0x94, 0x18, 0x90, 0x14,
226 0x83, 0xad, 0x84, 0x28, 0x46, 0xb8, 0x1c, 0xaa, 0x18, 0x24, 0xa0, 0xc4, 0x90, 0xc4, 0x06, 0x0e,
227 0x4c, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3e, 0x22, 0x2f, 0xab, 0x5a, 0x01, 0x00, 0x00,
228}
229
230// Reference imports to suppress errors if they are not otherwise used.
231var _ context.Context
232var _ grpc.ClientConn
233
234// This is a compile-time assertion to ensure that this generated file
235// is compatible with the grpc package it is being compiled against.
236const _ = grpc.SupportPackageIsVersion4
237
238// BookServiceClient is the client API for BookService service.
239//
240// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
241type BookServiceClient interface {
242 GetBookInfo(ctx context.Context, in *BookInfoParams, opts ...grpc.CallOption) (*BookInfo, error)
243 GetBookList(ctx context.Context, in *BookListParams, opts ...grpc.CallOption) (*BookList, error)
244}
245
246type bookServiceClient struct {
247 cc *grpc.ClientConn
248}
249
250func NewBookServiceClient(cc *grpc.ClientConn) BookServiceClient {
251 return &bookServiceClient{cc}
252}
253
254func (c *bookServiceClient) GetBookInfo(ctx context.Context, in *BookInfoParams, opts ...grpc.CallOption) (*BookInfo, error) {
255 out := new(BookInfo)
256 err := c.cc.Invoke(ctx, "/BookService/GetBookInfo", in, out, opts...)
257 if err != nil {
258     return nil, err
259 }
260 return out, nil
261}
262
263func (c *bookServiceClient) GetBookList(ctx context.Context, in *BookListParams, opts ...grpc.CallOption) (*BookList, error) {
264 out := new(BookList)
265 err := c.cc.Invoke(ctx, "/BookService/GetBookList", in, out, opts...)
266 if err != nil {
267     return nil, err
268 }
269 return out, nil
270}
271
272// BookServiceServer is the server API for BookService service.
273type BookServiceServer interface {
274 GetBookInfo(context.Context, *BookInfoParams) (*BookInfo, error)
275 GetBookList(context.Context, *BookListParams) (*BookList, error)
276}
277
278// UnimplementedBookServiceServer can be embedded to have forward compatible implementations.
279type UnimplementedBookServiceServer struct {
280}
281
282func (*UnimplementedBookServiceServer) GetBookInfo(ctx context.Context, req *BookInfoParams) (*BookInfo, error) {
283 return nil, status.Errorf(codes.Unimplemented, "method GetBookInfo not implemented")
284}
285func (*UnimplementedBookServiceServer) GetBookList(ctx context.Context, req *BookListParams) (*BookList, error) {
286 return nil, status.Errorf(codes.Unimplemented, "method GetBookList not implemented")
287}
288
289func RegisterBookServiceServer(s *grpc.Server, srv BookServiceServer) {
290 s.RegisterService(&_BookService_serviceDesc, srv)
291}
292
293func _BookService_GetBookInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
294 in := new(BookInfoParams)
295 if err := dec(in); err != nil {
296     return nil, err
297 }
298 if interceptor == nil {
299     return srv.(BookServiceServer).GetBookInfo(ctx, in)
300 }
301 info := &grpc.UnaryServerInfo{
302     Server:     srv,
303     FullMethod: "/BookService/GetBookInfo",
304 }
305 handler := func(ctx context.Context, req interface{}) (interface{}, error) {
306     return srv.(BookServiceServer).GetBookInfo(ctx, req.(*BookInfoParams))
307 }
308 return interceptor(ctx, in, info, handler)
309}
310
311func _BookService_GetBookList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
312 in := new(BookListParams)
313 if err := dec(in); err != nil {
314     return nil, err
315 }
316 if interceptor == nil {
317     return srv.(BookServiceServer).GetBookList(ctx, in)
318 }
319 info := &grpc.UnaryServerInfo{
320     Server:     srv,
321     FullMethod: "/BookService/GetBookList",
322 }
323 handler := func(ctx context.Context, req interface{}) (interface{}, error) {
324     return srv.(BookServiceServer).GetBookList(ctx, req.(*BookListParams))
325 }
326 return interceptor(ctx, in, info, handler)
327}
328
329var _BookService_serviceDesc = grpc.ServiceDesc{
330 ServiceName: "BookService",
331 HandlerType: (*BookServiceServer)(nil),
332 Methods: []grpc.MethodDesc{
333     {
334         MethodName: "GetBookInfo",
335         Handler:    _BookService_GetBookInfo_Handler,
336     },
337     {
338         MethodName: "GetBookList",
339         Handler:    _BookService_GetBookList_Handler,
340     },
341 },
342 Streams:  []grpc.StreamDesc{},
343 Metadata: "book.proto",
344}
345
346

3、服务器端代码


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
1package main
2
3import (
4   "MyKit" //import book.pb.go(protoc 生成的文件)
5   "context"
6   "github.com/go-kit/kit/endpoint"
7   grpc_transport "github.com/go-kit/kit/transport/grpc"
8   "google.golang.org/grpc"
9   "net"
10)
11
12type BookServer struct {
13  bookListHandler grpc_transport.Handler
14  bookInfoHandler grpc_transport.Handler
15}
16
17//通过grpc调用GetBookInfo时,GetBookInfo只做数据透传, 调用BookServer中对应Handler.ServeGRPC转交给go-kit处理
18func (s *BookServer) GetBookInfo(ctx context.Context, in *book.BookInfoParams) (*book.BookInfo, error) {
19  _, rsp, err := s.bookInfoHandler.ServeGRPC(ctx, in)
20  if err != nil {
21      return nil, err
22  }
23  return rsp.(*book.BookInfo), err
24}
25
26//通过grpc调用GetBookList时,GetBookList只做数据透传, 调用BookServer中对应Handler.ServeGRPC转交给go-kit处理
27func (s *BookServer) GetBookList(ctx context.Context, in *book.BookListParams) (*book.BookList, error) {
28  _, rsp, err := s.bookListHandler.ServeGRPC(ctx, in)
29  if err != nil {
30      return nil, err
31  }
32  return rsp.(*book.BookList), err
33}
34
35//创建bookList的EndPoint
36func makeGetBookListEndpoint() endpoint.Endpoint {
37  return func(ctx context.Context, request interface{}) (interface{}, error) {
38      //请求列表时返回 书籍列表
39      bl := new(book.BookList)
40      bl.BookList = append(bl.BookList, &book.BookInfo{BookId: 1, BookName: "Go入门到精通"})
41      bl.BookList = append(bl.BookList, &book.BookInfo{BookId: 2, BookName: "go-kit入门到精通"})
42      bl.BookList = append(bl.BookList, &book.BookInfo{BookId: 2, BookName: "go-micro入门到精通"})
43      return bl, nil
44  }
45}
46
47//创建bookInfo的EndPoint
48func makeGetBookInfoEndpoint() endpoint.Endpoint {
49  return func(ctx context.Context, request interface{}) (interface{}, error) {
50      //请求详情时返回 书籍信息
51      req := request.(*book.BookInfoParams)
52      b := new(book.BookInfo)
53      b.BookId = req.BookId
54      b.BookName = "Go与微服务"
55      return b, nil
56  }
57}
58
59func decodeRequest(_ context.Context, req interface{}) (interface{}, error) {
60  return req, nil
61}
62
63func encodeResponse(_ context.Context, req interface{}) (interface{}, error) {
64  return req, nil
65}
66
67func main() {
68  //包装BookServer
69
70  bookServer := new(BookServer)
71  //创建bookList的Handler
72  bookListHandler := grpc_transport.NewServer(
73      makeGetBookListEndpoint(),
74      decodeRequest,
75      encodeResponse,
76  )
77  //bookServer 增加 go-kit流程的 bookList处理逻辑
78  bookServer.bookListHandler = bookListHandler
79
80  //创建bookInfo的Handler
81  bookInfoHandler := grpc_transport.NewServer(
82      makeGetBookInfoEndpoint(),
83      decodeRequest,
84      encodeResponse,
85  )
86  //bookServer 增加 go-kit流程的 bookInfo处理逻辑
87  bookServer.bookInfoHandler = bookInfoHandler
88
89  //启动grpc服务
90  serviceAddress := ":50052"
91  ls, _ := net.Listen("tcp", serviceAddress)
92  gs := grpc.NewServer()
93  book.RegisterBookServiceServer(gs, bookServer)
94  gs.Serve(ls)
95}
96//Todo go-kit参考:https://blog.csdn.net/lihao19910921/article/details/80166399
97

4、客户端代码


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1package main
2
3import (
4   "MyKit"
5   "context"
6   "fmt"
7   "google.golang.org/grpc"
8)
9
10func main() {
11  serviceAddress := "127.0.0.1:50052"
12  conn, err := grpc.Dial(serviceAddress, grpc.WithInsecure())
13  if err != nil {
14      panic("connect error")
15  }
16  defer conn.Close()
17  bookClient := book.NewBookServiceClient(conn)
18  bi, _ := bookClient.GetBookInfo(context.Background(), &book.BookInfoParams{BookId: 1})
19  fmt.Print("获取书籍信息:\t")
20  fmt.Println("bookInfo:", bi.BookName)
21
22  bl, _ := bookClient.GetBookList(context.Background(), &book.BookListParams{Page: 1, Limit: 10})
23  fmt.Println("获取书籍列表:\t")
24  for _, b := range bl.BookList {
25      fmt.Println("bookId:", b.BookId, " => ", "bookName:", b.BookName)
26  }
27}
28
29

5、运行

首先启动Server端,处于监听阻塞状态。再运行client端:

go-kit实践之1:go-kit 与 grpc 结合开发微服务(go-kit endpoint的使用)

6、说明

go-kit抽象的endpoint:

一个Transport的Server 必须要拥有endPoint、decodeRequestFunc、encodeResponseFunc

1、 endPoint一个端点代表一个RPC,也就是我们服务接口中的一个函数

2、 decodeRequestFunc 请求参数解码函数

3、 encodeResponseFunc 返回参数编码函数

请求流程: 

请求->encodeResponseFunc -> endPoint -> decodeRequestFunc -> 返回输出

注:安装go-kit环境依赖内容比较多,有的时候因为网络问题(一般要访问外网),因此需要利用GitHub下载之后移动到对应的gopath中(具体问题只能结合自己的经验与百度了 O(∩_∩)O)。

给TA打赏
共{{data.count}}人
人已打赏
安全经验

Google AdSense 全面解析(申请+操作+作弊+忠告)

2021-10-11 16:36:11

安全经验

安全咨询服务

2022-1-12 14:11:49

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索