刘沙河 刘沙河
首页
  • Go语言基础

    • 数据类型
    • 反射
    • Go指针
  • Go语言进阶

    • go泛型
    • go条件编译
    • cgo教程
    • Go协程调度原理及GPM模型
    • Go内存管理
    • Go垃圾回收机制
    • Go语言内存对齐
  • Go语言实现原理

    • channel 实现原理
    • slice 实现原理
    • map 实现原理
    • sync.Mutex 实现原理
    • 乐观锁CAS 实现原理
    • singlefight 实现原理
  • gin框架

    • gin中间件原理
    • gin路由原理
  • gorm

    • GORM介绍和使用
    • GORM_CURD操作指南
  • go测试

    • benchmark基准测试
    • pprof 性能分析
  • python进阶

    • Numpy&Pandas
    • celery分布式任务队列
  • Django

    • Django 常见命令
    • middleware中间件
    • Django缓存系统
    • Django信号系统
    • Django REST Framework
  • Flask

    • Flask基础知识总结
    • Flask-SQLAlchemy
  • 爬虫

    • aiohttp
    • scrapy框架
  • Mysql

    • Mysql存储引擎和索引
    • MySQL主从复制
    • Mysql读写分离
    • 数据库分库分表
    • Mysql锁
    • Mysql事务和MVCC原理
    • 分库分表带来的读扩散问题
  • Redis

    • redis基础和数据类型
    • redis主从架构
    • redis哨兵架构
    • redis集群模式
    • 如何保证缓存和数据库双写一致
    • redis底层数据结构
    • redis分布式锁
  • Elasticsearch

    • es基本概念
    • es基础语法
    • es倒排索引
  • etcd

    • Go操作etcd
    • Raft原理
    • etcd分布式锁
  • kafka

    • 消息队列MQ总结
    • kafka 概述及原理
    • kafka 消费问题记录
    • 零拷贝技术
    • kafka分区规范
  • RabbitMQ

    • rabbitMQ基础
    • Go操作rabbitmq
  • RocketMQ

    • 可靠消息队列 rocketMQ
  • Http&Https

    • http&https
    • TCP和UDP
    • Ping 原理
  • RPC

    • RPC初识
    • grpc初识和实现
  • gRPC

    • grpc 初识
    • grpc 上下文 metadata
    • grpc 健康检查
    • grpc keepalive
    • grpc 命名解析
    • grpc 中间件&拦截器
    • grpc 负载均衡
    • grpc 身份认证
    • grpc 超时重试
    • grpc 链路追踪
    • grpc-gw将gRPC转RESTfu api
    • grpc-gw自定义选项
  • protobuf

    • protobuf 进阶
    • protobuf 编码原理
  • Docker

    • Docker基础
    • Docker常用命令
    • Dockerfile
    • Docker-Compose
    • Docker多阶段构建
    • Docker Config 教程
    • Docker Swarm 教程
    • Docker Stack 教程
    • Docker Buildx 教程
  • k8s

    • k8s 基础概念
    • k8s 集群架构
    • k8s 工作负载
    • Pod 网络
    • Service 网络
    • 外部接入网络
    • 一张图搞懂k8s各种pod
    • k8s 存储抽象
    • mac快速启动k8s
    • 自制申威架构k8s-reloader
  • go-kit

    • go-kit初识
    • go-kit启动http服务
    • go-kit集成gin启动服务
    • go-kit集成grpc和protobuf
    • go-kit中间件
    • go-kit服务注册发现与负载均衡
    • go-kit限流和熔断
    • go-kit链路追踪
    • go-kit集成Prometheus
  • 设计模式

    • 初识设计模式
    • 创建型模式
    • 结构型模式
    • 行为模式
  • 数据结构

    • 时间轮
    • 堆、双向链表、环形队列
    • 队列:优先队列
    • 队列:延迟队列
  • 算法

    • 递归算法
    • 枚举算法
    • 动态规划
    • 回溯算法
    • 分治算法
    • 贪心算法
    • LRU和LFU
    • 一致性哈希

花开半夏,半夏花开
首页
  • Go语言基础

    • 数据类型
    • 反射
    • Go指针
  • Go语言进阶

    • go泛型
    • go条件编译
    • cgo教程
    • Go协程调度原理及GPM模型
    • Go内存管理
    • Go垃圾回收机制
    • Go语言内存对齐
  • Go语言实现原理

    • channel 实现原理
    • slice 实现原理
    • map 实现原理
    • sync.Mutex 实现原理
    • 乐观锁CAS 实现原理
    • singlefight 实现原理
  • gin框架

    • gin中间件原理
    • gin路由原理
  • gorm

    • GORM介绍和使用
    • GORM_CURD操作指南
  • go测试

    • benchmark基准测试
    • pprof 性能分析
  • python进阶

    • Numpy&Pandas
    • celery分布式任务队列
  • Django

    • Django 常见命令
    • middleware中间件
    • Django缓存系统
    • Django信号系统
    • Django REST Framework
  • Flask

    • Flask基础知识总结
    • Flask-SQLAlchemy
  • 爬虫

    • aiohttp
    • scrapy框架
  • Mysql

    • Mysql存储引擎和索引
    • MySQL主从复制
    • Mysql读写分离
    • 数据库分库分表
    • Mysql锁
    • Mysql事务和MVCC原理
    • 分库分表带来的读扩散问题
  • Redis

    • redis基础和数据类型
    • redis主从架构
    • redis哨兵架构
    • redis集群模式
    • 如何保证缓存和数据库双写一致
    • redis底层数据结构
    • redis分布式锁
  • Elasticsearch

    • es基本概念
    • es基础语法
    • es倒排索引
  • etcd

    • Go操作etcd
    • Raft原理
    • etcd分布式锁
  • kafka

    • 消息队列MQ总结
    • kafka 概述及原理
    • kafka 消费问题记录
    • 零拷贝技术
    • kafka分区规范
  • RabbitMQ

    • rabbitMQ基础
    • Go操作rabbitmq
  • RocketMQ

    • 可靠消息队列 rocketMQ
  • Http&Https

    • http&https
    • TCP和UDP
    • Ping 原理
  • RPC

    • RPC初识
    • grpc初识和实现
  • gRPC

    • grpc 初识
    • grpc 上下文 metadata
    • grpc 健康检查
    • grpc keepalive
    • grpc 命名解析
    • grpc 中间件&拦截器
    • grpc 负载均衡
    • grpc 身份认证
    • grpc 超时重试
    • grpc 链路追踪
    • grpc-gw将gRPC转RESTfu api
    • grpc-gw自定义选项
  • protobuf

    • protobuf 进阶
    • protobuf 编码原理
  • Docker

    • Docker基础
    • Docker常用命令
    • Dockerfile
    • Docker-Compose
    • Docker多阶段构建
    • Docker Config 教程
    • Docker Swarm 教程
    • Docker Stack 教程
    • Docker Buildx 教程
  • k8s

    • k8s 基础概念
    • k8s 集群架构
    • k8s 工作负载
    • Pod 网络
    • Service 网络
    • 外部接入网络
    • 一张图搞懂k8s各种pod
    • k8s 存储抽象
    • mac快速启动k8s
    • 自制申威架构k8s-reloader
  • go-kit

    • go-kit初识
    • go-kit启动http服务
    • go-kit集成gin启动服务
    • go-kit集成grpc和protobuf
    • go-kit中间件
    • go-kit服务注册发现与负载均衡
    • go-kit限流和熔断
    • go-kit链路追踪
    • go-kit集成Prometheus
  • 设计模式

    • 初识设计模式
    • 创建型模式
    • 结构型模式
    • 行为模式
  • 数据结构

    • 时间轮
    • 堆、双向链表、环形队列
    • 队列:优先队列
    • 队列:延迟队列
  • 算法

    • 递归算法
    • 枚举算法
    • 动态规划
    • 回溯算法
    • 分治算法
    • 贪心算法
    • LRU和LFU
    • 一致性哈希
  • rpc

  • grpc

    • 【grpc】1.初识
    • 【grpc】2.上下文 metadata
    • 【grpc】3.健康检查
    • 【grpc】 4.keepalive
    • 【grpc】 5.命名解析
    • 【grpc】 6.中间件&拦截器
      • Unary Interceptor
        • 1. 服务端拦截器 UnaryServerInterceptor
        • 2. 客户端拦截器 UnaryClientInterceptor
      • Streaming Interceptor
        • 1. 服务端拦截器 StreamServerInterceptor
        • 2. 客户端拦截器 StreamClientInterceptor
      • 三方库
    • 【grpc】 7.负载均衡
    • 【grpc】 8.身份认证
    • 【grpc】 9.超时重试
    • 【grpc】 10.链路追踪
    • 【grpc】11.grpc-gw将gRPC 转 RESTful api
    • 【grpc】12.grpc-gw自定义选项
  • protobuf

  • rpc+grpc
  • grpc
bigox
2023-04-27
目录

【grpc】 6.中间件&拦截器

  • 拦截器又称为全局钩子、中间件

  • 构建gRPC应用程序时,客户端、服务端在远程方法执行之前,都可以执行一些通用的逻辑。诸如日志打印、参数校验、身份验证、性能度量指标等。gRPC包含多种通信模式,主要分为请求应答模式、流响应模式。因此根据需要拦截RPC的调用类型

  • gRPC拦截器可以分为两类:Unary Interceptor(一元拦截器)、Streaming Interceptor (流拦截器)。

    1. Unary Interceptor(一元拦截器)
    2. Streaming Interceptor (流拦截器)
  • 安装客户端和服务端拦截器分类可分为:

    1. 服务端 一元拦截器 UnaryServerInterceptor
    2. 客户端 一元拦截器 UnaryClientInterceptor
    3. 服务端 流拦截器
    4. 客户端 流拦截器
  • gRPC支持多个拦截器组成拦截器链,拦截器链之间按照顺序执行,以责任链模式的方式共同完成代码逻辑。

img

# Unary Interceptor

一元拦截器

# 1. 服务端拦截器 UnaryServerInterceptor

  • 定义

    // 一元拦截器
    type UnaryServerInterceptor func(
      ctx context.Context,
      req interface{},
      info *UnaryServerInfo,
      handler UnaryHandler
    ) (resp interface{}, err error)
    
    // 类型定义
    // info 
    type UnaryServerInfo struct {
    	// Server is the service implementation the user provides. This is read-only.
    	Server interface{}
    	// FullMethod is the full RPC method string, i.e., /package.service/method.
    	FullMethod string
    }
      
    // handler
    type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error)
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    参数名称 参数说明
    ctx context执行上下文
    req 客户端的request请求,包含请求参数
    info 服务名称, 通过该参数可以得知调用方法
    handler 客户端调用的gRPC方法(洋葱模型)
    resp response 返回信息
  • 代码示例

    func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
    
    	log.Printf("grpc server interceptor prehandler")
    	m, err := handler(ctx, req)
    	if err != nil {
    		log.Printf("RPC failed with error %v", err)
    	}
    	log.Printf("grpc server interceptor posthandler")
    	return m, err
    }
    
    
    //在调用NewServer时 传入拦截器
    s := grpc.NewServer(
            grpc.UnaryInterceptor(unaryInterceptor),
    )
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

# 2. 客户端拦截器 UnaryClientInterceptor

  • 定义

    // 客户端一元拦截器
    type UnaryClientInterceptor func(
      ctx context.Context,
      method string,
      req, reply interface{},
      cc *ClientConn,
      invoker UnaryInvoker,
      opts ...CallOption
    ) error
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    参数名称 参数说明
    ctx context执行上下文
    method gRPC方法名称
    req request body
    reply 服务端返回response
    cc client connectio
    invoker 调用的gRPC方法。如果执行此操作,则执行RPC
    opts 可选参数
  • 代码实现

    func unaryInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
    
       log.Printf("grpc client interceptor prehandler")
       start := time.Now()
       err := invoker(ctx, method, req, reply, cc, opts...)
       end := time.Now()
       log.Printf("grpc client interceptor posthandler RPC: %s, start time: %s, end time: %s, err: %v", method, start.Format("Basic"), end.Format(time.RFC3339), err)
       return err
    }
    
    //客户端在建立连接时 传入拦截器
    conn, err := grpc.Dial(*addr,grpc.WithUnaryInterceptor(unaryInterceptor))
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

# Streaming Interceptor

流式拦截器

# 1. 服务端拦截器 StreamServerInterceptor

  • 定义

    type StreamServerInterceptor func(srv interface{}, ss ServerStream, info *StreamServerInfo, handler StreamHandler) error
    
    1
  • 代码实现

    // 实现ServerStream接口
    type interceptorStream struct {
    	grpc.ServerStream
    }
    
    // 实现ServerStream接口 RecvMsg 方法
    func (w *interceptorStream) RecvMsg(m interface{}) error {
    	log.Printf("Receive a message (Type: %T) at %s", m, time.Now().Format(time.RFC3339))
    	return w.ServerStream.RecvMsg(m)
    }
    
    // 实现ServerStream接口 SendMsg 方法
    func (w *interceptorStream) SendMsg(m interface{}) error {
    	log.Printf("Send a message (Type: %T) at %v", m, time.Now().Format(time.RFC3339))
    	return w.ServerStream.SendMsg(m)
    }
    
    // 自定义流式拦截器
    func logStreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
    	log.Println("[pre stream] my stream server interceptor 1: ", info.FullMethod)
    
    	err := handler(srv, &interceptorStream{ss})
    
    	log.Println("[post stream] my stream server interceptor 1: ")
    	return err
    }
    
    grpcServer := grpc.NewServer(grpc.ChainStreamInterceptor(logStreamServerInterceptor))
    
    
    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

# 2. 客户端拦截器 StreamClientInterceptor

  • 定义

    type StreamClientInterceptor func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, streamer Streamer, opts ...CallOption) (ClientStream, error)
    
    1
  • 代码实现

    func logClientInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
    	log.Printf("before invoker. method: %+v, StreamDesc:%+v", method, desc)
    	clientStream, err := streamer(ctx, desc, cc, method, opts...)
    	log.Printf("before invoker. method: %+v", method)
    	return clientStream, err
    }
    
    conn,err := grpc.Dail(*addr, grpc.WithChainStreamInterceptor(logClientInterceptor))
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

# 三方库

https://github.com/grpc-ecosystem/go-grpc-middleware

#grpc
上次更新: 2023/05/04, 15:30:48
【grpc】 5.命名解析
【grpc】 7.负载均衡

← 【grpc】 5.命名解析 【grpc】 7.负载均衡→

最近更新
01
go与http代理
05-24
02
自制申威架构k8s-reloader
12-06
03
Docker Buildx 教程
12-01
更多文章>
Theme by Vdoing | Copyright © 2020-2024 小刘扎扎 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式