gRPC-07 客户端拦截器的实现

19 篇文章 11 订阅

代码地址

https://github.com/wanmei002/grpc-learn/tree/master/ch05

介绍

客户端拦截器主要是 内置客户端发送数据前和接收数据后的一些通用逻辑的实现。下图单词拼错了;拦截器: interceptor
客户端连接器

直接上代码吧

一元拦截器

拦截 grpc 的一元模式

需要实现 grpc/interceptor.go/type UnaryClientInterceptor func(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, invoker UnaryInvoker, opts ...CallOption) error 这个类型

func ClientUnaryInterceptor (
    ctx context.Context, method string, req, reply interface{},
    cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opt ...grpc.CallOption,
    ) error {
    log.Printf("method[%v];req[%v];reply[%v];cc[%+v];invoker[%T];\n",
                            method, req, reply, cc, invoker)
    // 上面都是前置逻辑操作
    err := invoker(ctx, method, req, reply, cc, opt...)// 向服务端发送请求
    // 下面都是后置逻辑操作
    if err != nil {
        log.Println("invoker err:", err)
    }
    log.Println("interceptor after")
    return err
}

流拦截器的实现

需要实现 grpc/interceptor.go/type StreamClientInterceptor func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, streamer Streamer, opts ...CallOption) (ClientStream, error) 这个类型

// 实现自定义的接收数据 和 发送数据前的逻辑
type clientStream struct {
    grpc.ClientStream
}
// 重写 接收后的逻辑
func (c *clientStream) RecvMsg(m interface{}) error {
    log.Printf("recv msg : [%T], val:[%v]\n", m , m)
    return c.ClientStream.RecvMsg(m)
}
// 重写 发送前的逻辑
func (c *clientStream) SendMsg(m interface{}) error {
    log.Printf("send msg:[%T]; val:[%v]\n", m, m)
    return c.ClientStream.SendMsg(m)
}

func NewClientStream(c grpc.ClientStream) grpc.ClientStream {
    return &clientStream{c}
}

// 流拦截器的实现
func ClientStreamInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn,
    method string, streamer grpc.Streamer, opt ...grpc.CallOption) (grpc.ClientStream, error) {
    pc, _, _, _ := runtime.Caller(0)
    log.Printf("call method[%v];stream desc[%+v]; method[%v]; streamer[%T];\n",
        runtime.FuncForPC(pc).Name(), desc, method, streamer)
    // 创建客户端流
    s, err := streamer(ctx, desc, cc, method, opt...)
    if err != nil {
        log.Println("client stream create failed; err:", err)
        return nil, err
    }
    // 流的发送和接收
    return NewClientStream(s), nil
}

跑起来

func main(){
    // 在这里注册拦截器
    d, err := grpc.Dial(":8093", grpc.WithInsecure(),
        grpc.WithUnaryInterceptor(interceptor.ClientUnaryInterceptor),// 注册一元拦截器
        grpc.WithStreamInterceptor(interceptor.ClientStreamInterceptor))// 注册 流拦截器
    
    if err != nil {
        log.Println("grpc dial failed; err:", err)
        return
    }
    defer d.Close()
    
    client := pb.NewProductClient(d)
    res, err := client.AddProduct(context.Background(), &pb.Order{
        Name:  "zzh",
        Items: []string{"hello", "zzh"},
        Desc:  "this is zzh",
    })
    
    if err != nil {
        log.Println("addProduct ret err; err:", err)
    }
    log.Printf("addProduct return res:%+v", res)
    fmt.Println(res.Code)
    
    stream, err := client.CommentProduct(context.Background(), &pb.ProductId{Id: "1234567"})
    if err != nil {
        log.Println("client comment product failed; err:", err)
    }
    log.Println("start recv server stream msg")
    if stream != nil {
        for {
            commentInfo, err := stream.Recv()
            if err != nil {
                log.Println("client stream recv failed; err:", err)
                break
            }
            log.Printf("recv data :[%+v]\n", commentInfo)
            log.Println("once return")
            return
        }
        
    }
    
    log.Println("client end")
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值