go-kit 微服务 使用GRPC(并为每个请求添加ID)
2020-01-10 本文已影响0人
hwholiday
grpc
- gRPC是一个高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发
- grpc使用 案例
简介
- 通过grpc实现一个用户中心实现简单的鉴权中心并返回用户token
- 上篇文章《go-kit 微服务 身份认证(JWT)》已经实现的一个http的鉴权中心,所以我们只需要改变transport层逻辑
- 编写ProtoBuf
//service.proto
syntax = "proto3";
package pb;
import "user.proto";
service User {
rpc RpcUserLogin (Login) returns (LoginAck) {
}
}
//user.proto
message Login {
string Account = 1;
string Password = 2;
}
message LoginAck {
string Token = 1;
}
- 编译ProtoBuf
protoc --go_out=plugins=grpc:. *.proto
transport层修改
- 定义grpcServer结构体
type grpcServer struct {
login grpctransport.Handler
}
- 实现RpcUserLogin接口
func (s *grpcServer) RpcUserLogin(ctx context.Context, req *pb.Login) (*pb.LoginAck, error) {
_, rep, err := s.login.ServeGRPC(ctx, req)
if err != nil {
return nil, err
}
return rep.(*pb.LoginAck), nil
}
- 将endpoint的方法加载到grpcServer对象中
func NewGRPCServer(endpoint v5_endpoint.EndPointServer, log *zap.Logger) pb.UserServer {
options := []grpctransport.ServerOption{
grpctransport.ServerBefore(func(ctx context.Context, md metadata.MD) context.Context {
ctx = context.WithValue(ctx, v5_service.ContextReqUUid, md.Get(v5_service.ContextReqUUid))
return ctx
}),
grpctransport.ServerErrorHandler(NewZapLogErrorHandler(log)),
}
return &grpcServer{login: grpctransport.NewServer(
endpoint.LoginEndPoint,
RequestGrpcLogin,
ResponseGrpcLogin,
options...,
)}
}
修改main方法
utils.NewLoggerServer()
golangLimit := rate.NewLimiter(10, 1)
server := v5_service.NewService(utils.GetLogger())
endpoints := v5_endpoint.NewEndPointServer(server, utils.GetLogger(), golangLimit)
grpcServer := v5_transport.NewGRPCServer(endpoints, utils.GetLogger())
utils.GetLogger().Info("server run :8881")
grpcListener, err := net.Listen("tcp", ":8881")
if err != nil {
utils.GetLogger().Warn("Listen", zap.Error(err))
os.Exit(0)
}
baseServer := grpc.NewServer(grpc.UnaryInterceptor(grpctransport.Interceptor))
pb.RegisterUserServer(baseServer, grpcServer)
if err = baseServer.Serve(grpcListener); err != nil {
utils.GetLogger().Warn("Serve", zap.Error(err))
os.Exit(0)
}
编写客户端
- go-kit 客户端
func NewGRPCClient(conn *grpc.ClientConn, log *zap.Logger) v5_service.Service {
options := []grpctransport.ClientOption{
grpctransport.ClientBefore(func(ctx context.Context, md *metadata.MD) context.Context {
UUID := uuid.NewV5(uuid.Must(uuid.NewV4()), "req_uuid").String()
log.Debug("给请求添加uuid", zap.Any("UUID", UUID))
md.Set(v5_service.ContextReqUUid, UUID)
ctx = metadata.NewOutgoingContext(context.Background(), *md)
return ctx
}),
}
var loginEndpoint endpoint.Endpoint
{
loginEndpoint = grpctransport.NewClient(
conn,
"pb.User",
"RpcUserLogin",
RequestLogin,
ResponseLogin,
pb.LoginAck{},
options...).Endpoint()
}
return v5_endpoint.EndPointServer{
LoginEndPoint: loginEndpoint,
}
}
func RequestLogin(_ context.Context, request interface{}) (interface{}, error) {
req := request.(*pb.Login)
return &pb.Login{Account: req.Account, Password: req.Password}, nil
}
func ResponseLogin(_ context.Context, response interface{}) (interface{}, error) {
resp := response.(*pb.LoginAck)
return &pb.LoginAck{Token: resp.Token}, nil
}
- go-kit 客户端 调用方法
logger := logtool.NewLogger(
logtool.SetAppName("go-kit"),
logtool.SetDevelopment(true),
logtool.SetLevel(zap.DebugLevel),
)
conn, err := grpc.Dial("127.0.0.1:8881", grpc.WithInsecure())
if err != nil {
t.Error(err)
return
}
defer conn.Close()
svr := NewGRPCClient(conn, logger)
ack, err := svr.Login(context.Background(), &pb.Login{
Account: "hwholiday",
Password: "123456",
})
if err != nil {
t.Error(err)
return
}
t.Log(ack.Token)
- grpc原生客户端
serviceAddress := "127.0.0.1:8881"
conn, err := grpc.Dial(serviceAddress, grpc.WithInsecure())
if err != nil {
panic("connect error")
}
defer conn.Close()
userClient := pb.NewUserClient(conn)
UUID := uuid.NewV5(uuid.Must(uuid.NewV4()), "req_uuid").String()
md := metadata.Pairs( v5_service.ContextReqUUid, UUID)
ctx := metadata.NewOutgoingContext(context.Background(), md)
res, err := userClient.RpcUserLogin(ctx, &pb.Login{
Account: "hw",
Password: "123",
})
if err != nil {
t.Error(err)
return
}
t.Log(res.Token)
传递客户端请求ID到服务端代码
- 客户端
......
UUID := uuid.NewV5(uuid.Must(uuid.NewV4()), "req_uuid").String()
log.Debug("给请求添加uuid", zap.Any("UUID", UUID))
md.Set(v5_service.ContextReqUUid, UUID)
ctx = metadata.NewOutgoingContext(context.Background(), *md)
......
- 服务端
......
ctx = context.WithValue(ctx, v5_service.ContextReqUUid, md.Get(v5_service.ContextReqUUid))
......
运行日志
//客户端
2020-01-07 15:42:24 INFO logtool/log.go:89 [NewLogger] success
2020-01-07 15:42:24 DEBUG client/client.go:20 给请求添加uuid {"UUID": "a8360f58-6f0d-588f-83c9-b3dc00fe60f6"}
--- PASS: TestGrpcClient (0.00s)
grpc_test.go:36: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJOYW1lIjoiaHdob2xpZGF5IiwiRGNJZCI6MSwiZXhwIjoxNTc4MzgyOTc0LCJpYXQiOjE1NzgzODI5NDQsImlzcyI6ImtpdF92NCIsIm5iZiI6MTU3ODM4Mjk0NCwic3ViIjoibG9naW4ifQ.PSd1mWjfePR0IP3cw8gF9yN3IaNQDt9TaDpSk4QzUDc
PASS
//服务端
2020-01-07 15:42:16 INFO logtool/log.go:89 [NewLogger] success
2020-01-07 15:42:16 INFO v5_user/main.go:23 server run :8881
2020-01-07 15:42:24 DEBUG v5_service/service.go:28 [a8360f58-6f0d-588f-83c9-b3dc00fe60f6] {"调用 v5_service rvice": "Login 处理请求"}
2020-01-07 15:42:24 DEBUG v5_service/service.go:35 [a8360f58-6f0d-588f-83c9-b3dc00fe60f6] {"调用 v5_service rvice": "Login 处理请求", "处理返回值": "Token:\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJOYW1lIjoiaHdob2xpZGF5IiwiRGNJZCI6joxNTc4MzgyOTc0LCJpYXQiOjE1NzgzODI5NDQsImlzcyI6ImtpdF92NCIsIm5iZiI6MTU3ODM4Mjk0NCwic3ViIjoibG9naW4ifQ.PSd1mWjfePR0IP3cw8gF9yN3IaNQDt9TaDpSk4QzUDc\" "}
2020-01-07 15:42:24 DEBUG v5_service/middleware.go:31 [a8360f58-6f0d-588f-83c9-b3dc00fe60f6] {"调用 Login logMilewareServer": "Login", "req": "Account:\"hwholiday\" Password:\"123456\" ", "res": "Token:\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJOYW1lIjoiaHdob2xpZGF5IiwiRGNJZCI6MSwiZXhwIjoxNTc4MzgyOTc0LCJpYXQiOjE1NzgzODI5NDQsImlzcyI6ImtpdF92NCIsIm5iZiI6MTU3ODM4Mjk0NCwic3ViIjoibG9naW4ifQ.PSd1mWjfePR0IP3cw8gF9yN3IaNQDt9TaDpSk4QzUDc\" ", "err": null}
2020-01-07 15:42:24 DEBUG v5_endpoint/middleware.go:18 [a8360f58-6f0d-588f-83c9-b3dc00fe60f6] {"调用 v4_endpointoggingMiddleware": "处理完请求", "耗时毫秒": 0}
结语
- 这里只实现了一个煎蛋的grpc在go-kit的使用场景
- 欢迎添加QQ一起讨论