文章目录
- 七、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. 响应拦截器 (逆向顺序)");
}
}
- 客户端拦截器执行顺序: 添加顺序 → 实际调用 → 响应顺序
- 服务器拦截器执行顺序: 添加顺序 → 实际处理 → 响应顺序