大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
状态与错误
gRPC 用 Status(code + description)与 Metadata 传递错误;客户端通过 StatusRuntimeException 处理。与 REST 的 HTTP 状态码 概念对应、映射非 1:1。
学习目标
- 使用标准
Status.Code(NOT_FOUND、INVALID_ARGUMENT等) - 在 Metadata 中传递 trace-id、业务错误码
- 配置 deadline 避免级联阻塞
核心内容
Status 对照 REST
| gRPC Code | 近似 REST | 本站示例 |
|---|---|---|
OK | 200 | 正常返回 track |
NOT_FOUND | 404 | slug 不存在 |
INVALID_ARGUMENT | 400 | 空 slug |
UNAUTHENTICATED | 401 | 缺 mTLS/ token |
DEADLINE_EXCEEDED | 504 | 下游超时 |
UNAVAILABLE | 503 | 服务未启动 |
REST TrackController 返回 ResponseEntity.notFound();gRPC lab 用 Status.NOT_FOUND——同一业务,不同传输语义。
服务端抛错
if (req.getSlug().isBlank()) {
resp.onError(Status.INVALID_ARGUMENT
.withDescription("slug required")
.asRuntimeException());
return;
}
resp.onError(Status.NOT_FOUND
.withDescription("track: " + req.getSlug())
.asRuntimeException());
Metadata 与拦截器
Metadata.Key<String> TRACE =
Metadata.Key.of("x-trace-id", Metadata.ASCII_STRING_MARSHALLER);
Metadata trailers = new Metadata();
trailers.put(TRACE, MDC.get("traceId"));
resp.onError(Status.INTERNAL.asRuntimeException(trailers));
Spring 可用 ServerInterceptor 统一注入 trace,对齐 spring-boot-essentials 日志 MDC。微服务链路透传见 spring-cloud-essentials Sleuth/Micrometer。
Deadline
// 客户端
stub.withDeadlineAfter(3, TimeUnit.SECONDS).getTrack(req);
// 服务端检查
if (Context.current().isCancelled()) { /* 尽早退出 */ }
公开 /tracks 仍用 HTTP timeout + 网关限流;gRPC deadline 主要 服务间 防护。
练习
- 触发
NOT_FOUND,打印getStatus().getCode() - 设置 1ms deadline,观察
DEADLINE_EXCEEDED - 对比 REST 404 JSON body 与 gRPC 纯 Status 差异
小结
错误 = Status + 可选 Metadata;deadline 是微服务韧性基础。 下一课 gRPC-Gateway 与 REST 桥接。