面试知识库
进阶

gRPC拦截器与错误处理#

一句话答案#

gRPC 拦截器分客户端/服务端两侧,类似 Spring 的 AOP 切面,用于统一处理日志、认证、限流、链路追踪等横切关注点;错误处理通过 Status Code + Metadata 传递结构化错误信息。

核心要点

拦截器分类#

客户端拦截器(ClientInterceptor):
  请求前 → 添加 Token/TraceId/Metadata → 发送 → 响应后 → 记录耗时/错误

服务端拦截器(ServerInterceptor):
  收到请求 → 鉴权/限流/日志 → 转发给 Service 实现 → 返回前 → 后处理
plaintext

服务端拦截器示例#

客户端拦截器示例#

gRPC Status Code#

Code含义对应场景
OK (0)成功-
CANCELLED (1)客户端取消超时取消
INVALID_ARGUMENT (3)参数错误校验失败
NOT_FOUND (5)资源不存在查询空结果
PERMISSION_DENIED (7)无权限RBAC 拒绝
UNAUTHENTICATED (16)未认证Token 无效/过期
RESOURCE_EXHAUSTED (8)资源耗尽限流
INTERNAL (13)内部错误未知异常
UNAVAILABLE (14)服务不可用熔断/宕机
DEADLINE_EXCEEDED (4)超时deadline 到期

结构化错误传递#

// 服务端返回详细错误
Status status = Status.INVALID_ARGUMENT
    .withDescription("order_id must be positive");
Metadata trailers = new Metadata();
trailers.put(ERROR_DETAIL_KEY, "{\"field\":\"order_id\",\"reason\":\"negative\"}");
responseObserver.onError(status.asRuntimeException(trailers));

// 客户端解析
try {
    stub.getOrder(request);
} catch (StatusRuntimeException e) {
    Status status = e.getStatus();
    Metadata trailers = e.getTrailers();
    // 根据 status.getCode() 做不同处理
}
java

拦截器链执行顺序#

客户端: Interceptor1 → Interceptor2 → ... → 发送请求
服务端: Interceptor1 → Interceptor2 → ... → Service 实现
        (先注册的先执行)
plaintext
面试回答(2分钟版)

gRPC 拦截器分客户端和服务端两侧,类似 Spring AOP 的切面机制。服务端 ServerInterceptor 拦截请求做鉴权、限流、日志;客户端 ClientInterceptor 在请求前注入 TraceId、Token 等 Metadata,响应后记录耗时。多个拦截器按注册顺序形成链。错误处理方面,gRPC 定义了 16 种 Status Code,比如 UNAUTHENTICATED 未认证、RESOURCE_EXHAUSTED 限流、DEADLINE_EXCEEDED 超时。服务端通过 Status + Metadata 返回结构化错误,客户端 catch StatusRuntimeException 按 Code 分类处理。实践中常用拦截器实现:JWT 鉴权拦截器、Sentinel 限流拦截器、OpenTelemetry 链路追踪拦截器。和 Spring 拦截器的区别是 gRPC 拦截器工作在 RPC 层而非 HTTP 层,粒度更细(可以拦截 Streaming 的每条消息)。

追问与易错

追问方向:

  • “拦截器和 Spring AOP 什么关系?”→ 独立的,gRPC 拦截器在 RPC 层,Spring AOP 在 Bean 方法层
  • “怎么做全局异常处理?”→ 服务端拦截器 catch 所有异常,统一转为 gRPC Status 返回
  • “Deadline 怎么传播?”→ 客户端设置 deadline,通过 Metadata 传到下游服务,每一跳检查剩余时间

易错点:

  • ❌ “gRPC 用 HTTP 状态码”——用自己的 16 种 Status Code,和 HTTP 200/404 无关
  • ❌ “拦截器能修改请求体”——只能操作 Metadata(header),不能改 message body
  • ❌ “UNAVAILABLE 就是服务挂了”——也可能是限流或负载均衡无可用节点