美文网首页
go-kit 微服务 使用GRPC(并为每个请求添加ID)

go-kit 微服务 使用GRPC(并为每个请求添加ID)

作者: hwholiday | 来源:发表于2020-01-10 14:43 被阅读0次

    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一起讨论

    完整代码地址

    联系 QQ: 3355168235

    相关文章

      网友评论

          本文标题:go-kit 微服务 使用GRPC(并为每个请求添加ID)

          本文链接:https://www.haomeiwen.com/subject/ahopactx.html