gRPC从0到1系列【20】

文章目录

  • 七、gRPC拦截器
    • [7.1 拦截器概述](#7.1 拦截器概述)
      • [7.1.1 什么是gRPC拦截器?](#7.1.1 什么是gRPC拦截器?)
      • [7.1.2 拦截器的类型划分](#7.1.2 拦截器的类型划分)
      • [7.1.3 核心接口](#7.1.3 核心接口)
      • [7.1.4 调用链](#7.1.4 调用链)
      • [7.1.5 流程图](#7.1.5 流程图)
    • [7.2 工作原理与生命周期](#7.2 工作原理与生命周期)
      • [7.2.1 拦截器处理流程](#7.2.1 拦截器处理流程)
      • [7.2.2 拦截器的执行顺序](#7.2.2 拦截器的执行顺序)

七、gRPC拦截器

7.1 拦截器概述

7.1.1 什么是gRPC拦截器?

gRPC 拦截器是一种AOP (面向切面编程) 的实现,允许你在 RPC 调用的生命周期的特定节点(如调用前、调用后、出错时)注入自定义逻辑,而无需修改 RPC 方法本身的业务代码。

你可以把拦截器想象成 RPC 调用的 "安检员" 或 "门卫"

  • 在调用到达业务逻辑之前:检查调用者的身份(认证)、记录请求日志、修改或添加元数据。
  • 在业务逻辑执行之后:记录响应日志、收集性能指标(如耗时)、修改或添加响应的元数据。
  • 在发生异常时 :记录错误日志、将业务异常转换为标准的 gRPC Status 错误。

拦截器的核心价值在于解耦:将与业务无关的通用功能(如日志、监控、安全)从业务代码中分离出来,实现代码的模块化和复用。

7.1.2 拦截器的类型划分

gRPC 拦截器分为 客户端服务端 两大类,每类又根据 RPC 模式细分:

✅ 1. 服务器端拦截器【ServerInterceptor】

RPC 类型 拦截器方法签名(Java)
Unary(一元) UnaryServerInterceptor
Server Streaming ServerStreamingServerInterceptor
Client Streaming ClientStreamingServerInterceptor
Bidirectional Streaming BidiStreamingServerInterceptor

通用做法 :使用 ServerInterceptor 接口(底层自动适配所有类型)

✅ 2. 客户端拦截器【ClientInterceptor】

RPC 类型 拦截器方法签名(Java)
Unary UnaryClientInterceptor
Streaming(三种流) StreamingClientInterceptor

通用做法 :使用 ClientInterceptor 接口

7.1.3 核心接口

java 复制代码
// 服务端拦截器
public interface ServerInterceptor {
  <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
      ServerCall<ReqT, RespT> call,
      Metadata headers,
      ServerCallHandler<ReqT, RespT> next);
}

// 客户端拦截器
public interface ClientInterceptor {
  <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
      MethodDescriptor<ReqT, RespT> method,
      CallOptions callOptions,
      Channel next);
}

7.1.4 调用链

bash 复制代码
客户端: 
[App] → [Interceptor1] → [Interceptor2] → ... → [Network]

服务端:
[Network] → [Interceptor1] → [Interceptor2] → ... → [Business Logic]
  • next 参数:代表"下一个拦截器或最终处理者"
  • 必须调用 next.xxx(),否则调用链中断!

7.1.5 流程图

7.2 工作原理与生命周期

7.2.1 拦截器处理流程

拦截器的工作基于责任链模式 (Chain of Responsibility)。你可以为一个 gRPC 通道(Channel)或服务注册多个拦截器,它们会按特定顺序形成一个 "拦截器链"。

一元 RPC (Unary RPC) 的拦截流程 (以服务端为例):
Client InterceptorChain LoggingInterceptor AuthInterceptor BusinessLogic 1. Send RPC Request 2. Invoke interceptor 3. Check credentials in Metadata 4. Proceed to next interceptor 5. Log request details 6. Proceed to business logic 7. Execute business code 8. Return response 9. Log response details 10. Return response 11. Return response 12. Send RPC Response 4. Return error (UNAUTHENTICATED) 5. Send RPC Error alt [Valid] [Invalid] Client InterceptorChain LoggingInterceptor AuthInterceptor BusinessLogic

核心方法:

  • Context: 每个 RPC 调用都关联一个 Context对象,它像一个 "上下文" 或 "环境",可以在拦截器链和业务逻辑之间传递数据(如用户身份信息)。它是不可变的,但可以通过 withValue() 创建一个包含新值的子上下文。
  • next 在拦截器的实现中,ServerCallHandler (服务端) 或 ClientCall (客户端) 对象通常被命名为 next。调用 next.startCall()或 next.invoke()意味着将 RPC 调用传递给链中的下一个拦截器 。如果当前拦截器是最后一个,则 next 指向实际的业务逻辑实现。如果不调用 next,整个调用链将被中断。

7.2.2 拦截器的执行顺序

java 复制代码
package com.example.grpc.interceptor;

import io.grpc.*;

/**
 * gRPC 拦截器核心概念演示
 */
public class InterceptorConcepts {
    
    /**
     * 拦截器执行顺序示意图
     * 
     * 客户端拦截器执行顺序: 添加顺序 → 实际调用 → 响应顺序
     * 服务器拦截器执行顺序: 添加顺序 → 实际处理 → 响应顺序
     */
    
    // 客户端调用流程
    public static void demonstrateClientFlow() {
        System.out.println("=== 客户端拦截器执行顺序 ===");
        System.out.println("1. 请求拦截器 (正向顺序)");
        System.out.println("2. 实际RPC调用");
        System.out.println("3. 响应拦截器 (逆向顺序)");
    }
    
    // 服务器调用流程  
    public static void demonstrateServerFlow() {
        System.out.println("=== 服务器拦截器执行顺序 ===");
        System.out.println("1. 请求拦截器 (正向顺序)");
        System.out.println("2. 实际服务处理");
        System.out.println("3. 响应拦截器 (逆向顺序)");
    }
}
  • 客户端拦截器执行顺序: 添加顺序 → 实际调用 → 响应顺序
  • 服务器拦截器执行顺序: 添加顺序 → 实际处理 → 响应顺序
相关推荐
躺平大鹅2 小时前
Java面向对象入门(类与对象,新手秒懂)
java
初次攀爬者2 小时前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺3 小时前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
Derek_Smart4 小时前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot
NE_STOP5 小时前
MyBatis-mybatis入门与增删改查
java
孟陬8 小时前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端
想用offer打牌8 小时前
一站式了解四种限流算法
java·后端·go
华仔啊9 小时前
Java 开发千万别给布尔变量加 is 前缀!很容易背锅
java
也些宝10 小时前
Java单例模式:饿汉、懒汉、DCL三种实现及最佳实践
java