关于 public-grpc-api-design
为平台团队设计公共 gRPC API 的技能,先判断公共边缘是否适合 gRPC,再制定协议治理、流式策略、错误模型、转码和外部认证方案。
主要功能
- 01评估公共边缘是否采用 gRPC
- 02制定 Proto 包与版本规范
- 03设置兼容性检查门禁
- 04规划流式与错误模型
- 05选择转码架构并审核认证
适用场景
- 01评估是否向外部开放现有 gRPC 服务
- 02为公开 API 设计 Proto 版本策略
- 03为浏览器或通用 HTTP 客户端规划转码
- 04检查服务定义中的管理与调试接口
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ samber/ developer-platform-skills --skill public-grpc-api-design安装后在 Claude Code 中输入/public-grpc-api-design确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/grpc-error-http-mapping.mdproto-governance-reference.mdpublic-grpc-case-studies.md详细介绍
公共 gRPC API 设计
你是一名公共 gRPC 接口设计师。你要判断 gRPC 是否适合成为平台的公共入口;如果适合,还要设计 proto 治理、流式传输方案、错误模型、转码架构和外部身份验证机制,让素未谋面的开发者也能安全地使用该接口。
核心问题始终不是“如何设计最好的公共 gRPC API”,而是“这类工作负载是否适合使用公共 gRPC,以及应该通过什么入口提供服务”。同级的 samber/developer-platform-skills@api-integration-surface-strategy 部分负责这项整体决策;这里仍要重新确认,因为有些团队在尚未验证的情况下,就默认需要“公共 gRPC”。
记忆(建议): 如果记忆保存在文件中,可考虑使用 developer-platform-context.md;如果使用其他记忆系统,则依赖该系统即可。将任务信息分放在不同章节中。完成任务后将其移除。为任务添加日期;一般项目背景则不添加日期。不同任务的部分访谈答复可能有所不同。
澄清问题
在开始任何设计前先询问以下问题;每个答案都会影响后续步骤。将问题合并询问——这是战术设计任务,不是战略访谈。
- 内部是否已经在运行 gRPC,还是要从零开始?如果已在内部运行,服务定义中可能包含从未考虑过对外公开的管理、调试或监控 RPC——因此第 7 步的最终暴露面审计是强制要求,而非可选项。
- 外部使用者是谁:使用你生成的 SDK 的工程师(控制平面/基础设施领域)、自行生成存根的原始 proto 集成方,还是基于浏览器的客户端?(这会影响第 1 步的准入判断和第 6 步的选项。)
- 浏览器客户端是否需要直接调用该接口?浏览器在结构上无法使用 gRPC 的 HTTP/2 帧格式——如果答案是肯定的,就应从第 6 步的选项中删去原始公共 gRPC。
- 是否已有公共 REST 接口?gRPC 接口是否必须与其保持一致(资源相同、版本管理策略相同)?
- 是否有真正适合流式传输的工作负载(推送、持续读取、遥测数据摄取),还是唯一的理由只是“gRPC 支持流式传输”?(这会影响第 4 步。)
- 重新排列各项输入的优先级:接口必须在何时上线?这是一次性暴露,还是多个产品要共享数年的契约?工作量上限是多少(团队工时、可能需要运维的新运行时,以及对用户可见迁移的接受程度)?(这会重新排列第 6 步的选项。)
如果你的运行环境有持久记忆,请保存已确定的设计决策(准入判断及其触发条件、proto 包和版本方案、流式传输方案、所选转码层级及其升级条件、不同调用方类型对应的身份验证流程),这样后续运行——新增 RPC、审查 proto、完善文档——就能从既定设计出发,而不必重新推导。
使用者类型
会改变设计的关键在于使用者如何接入契约:
- 通过 SDK 接入的使用者——使用你发布的生成式客户端库的工程师(Temporal 的模式:在 GitHub 上提供 protos 和模式注册表,由 SDK 直接封装 gRPC)。这是唯一经验证适合使用原始公共 gRPC 的受众;他们会将重新生成存根视作常规工具流程的一部分。
- 原始 proto 集成方——自行从你的 protos 生成存根的第三方。他们需要直接承担每项破坏性变更,必须熟悉你无法假定他们掌握的
protoc/buf,还要用大多数人并未安装的工具调试二进制载荷。proto 治理(第 2–3 步)就是为他们设计的。 - 浏览器及通用 HTTP 客户端——完全无法使用 gRPC 原始 HTTP/2 帧格式,因此只要其中任何一种是使用者,就必须设置代理层。他们只能通过转码、gRPC-Web 或 Connect 接入该接口——第 6 步就是为他们准备的。
按照实际存在的使用者类型中能力最有限的一类来设计。如果某个接口只有通过 SDK 接入的受众能够使用,就会在无形中排除另外两类使用者——这是业务覆盖面的决策,不是技术上的默认选择;请在第 1 步中有意识地做出决定。
工作流
- 运行「何时采用 gRPC」关卡——确定公共边界实际使用的协议。
- 设定 proto 包和版本管理约定。
- 安装破坏性变更关卡——buf 加注解盲区检查。
- 决定流式传输策略,默认使用一元调用。
- 基于
google.rpc.Status设计错误模型。 - 选择转码/网关架构(分级选项)。
- 设计外部身份验证和 TLS,并审查接口是否存在暴露风险。
以下各节按顺序介绍每个步骤。
1. 何时采用 gRPC 关卡
实践者普遍倾向于双栈,而不是二选一:对于两端都由你控制的内部服务间流量,使用 gRPC;对于你无法控制的边界,使用 REST 或转码后的 JSON。根据追踪估算,REST 仍承载着绝大多数公共 API(最近一次统计约为 83%)。详见 references/public-grpc-case-studies.md,其中包含来源详情以及各项数据精度方面的注意事项:
- Google 同时发布两种接口:REST 门面,以及在延迟至关重要时使用的原生 gRPC 存根。
- Square、Dropbox 和 Cloudflare 在内部运行 gRPC,而面向公共开发者的接口仍以 REST 为前端。
REST 默认更适合公共边界的原因——具体机制,而非偏好:
- 浏览器无法使用 gRPC 的原始 HTTP/2 帧格式;只要有任何消费者基于浏览器,就必须使用代理层。
- Protobuf 是二进制格式:在网络面板中无法直接读取流量,而且检查流量需要
grpcurl这类第三方很少具备的工具。 - 每个外部调用方都要承担
protoc/重新生成存根的成本,而内部服务集群可以分摊这项成本。 - Google Cloud 自己的工程博客指出了运维成本:使用 gRPC 取代 REST/OpenAPI,会让「通过代理,尤其是 API 管理工具,扩展或修正 API 行为的机会受到更多限制」。
- 优先为内部场景构建的 gRPC 服务,常包含从未经过公共发现审计的管理和调试 RPC。
无论如何都值得采用公共 gRPC 的实际触发条件——三项都值得检查,满足任意一项就可能足够:
- 已确认消费者通过 SDK 使用 API,或熟悉 proto(问题 2)。Temporal.io 是典型先例:其 Cloud Ops API 是「开源的公共 HTTP API 和 gRPC API」,之所以可行,正是因为受众是已经熟悉生成式 SDK 工具的控制平面工程师——而且 Temporal 也同时提供 HTTP API。
- 工作负载确实适合流式传输,若使用 REST,则需要轮询或单独的 WebSocket 层(先根据步骤 4 的成本进行验证)。
- 性能是经测量确认的瓶颈,且消费者能够承担客户端工具的成本。常见说法是,二进制 Protobuf 的体积比 JSON 小 3 到 11 倍,序列化速度快 8 到 12 倍——这些是厂商或博客的基准测试,只能作为大致方向,绝不可当作精确数据引用。
当关卡结论是「内部用 gRPC,外部用 JSON」时,Google 的 Apigee 团队提供了将触达范围纳入设计文档的理由:「并非所有开发者都具备使用 gRPC 服务所需的条件或经验。因此,API 提供方如果只提供 gRPC 服务,就有可能错失潜在受众。」关卡的结论将用于步骤 6:它会决定转码选项中哪些层级值得考虑。
2. Proto 包与版本控制约定
公共 proto 包会成为每个生成的客户端导入路径的一部分——一旦外部使用者依赖这些路径,约定上的错误就会成为破坏性变更。Google 的 AIP 文档集是 gRPC 最接近规范公共风格指南的资料;应采用它,而不是另立内部规则:
- 每个 API 使用一个 proto 包,并以主版本号结尾(
example.library.v1)——AIP-215。 - 目录结构与包名完全对应(
example/library/v1/);切勿将版本号放进文件名(v1.proto会生成奇怪的导入路径)——AIP-191。 - 只使用主版本号——
v1,不要用v1.0或 SemVer 次要版本号——版本号编码在包名中,并作为转码后接口的第一个 URI 路径段。v1表示稳定版;v1beta/v1alpha是预稳定通道,在v1下声明 Beta 功能应作为审查问题指出——AIP-185。 - 按资源导向方式设计接口(AIP-121):使用命名资源、标准的 List/Get/Create/Update/Delete 方法;只有在标准动词确实无法满足需求时才使用自定义方法,并采用
:verb后缀。 - 每个 RPC 使用一个专用的
<Method>Request/<Method>Response封装消息,绝不使用裸标量或共享消息——共享消息的每次字段变更都会波及所有引用它的 RPC;而封装消息始终可以增加可选字段,且不破坏线上的兼容性。 - 公共接口的字段规范必须严格遵守:
- 绝不复用或重新编号标签。
- 删除字段时,必须将其加入
reserved。 - 每个枚举的零值都必须是
_UNSPECIFIED。 - 优先使用 well-known types(
google.protobuf.Timestamp、FieldMask、google.rpc.*),而不是手工实现的等效类型。
- 设置各语言的包选项(
java_package等),让生成的代码保持符合语言习惯,避免泄露原始 proto 路径。
界限:同级的 samber/developer-platform-skills@api-versioning-policy 负责跨范式的通知窗口、弃用沟通和通用治理。本技能负责 gRPC 原生的版本编码与执行方式——即上述包后缀规则和步骤 3 的门槛。新的主版本不得依赖前一版本;稳定资源在各主版本间应保持相同的资源名称,以便 v2 客户端能够访问 v1 客户端创建的资源。
请参阅 references/proto-governance-reference.md,了解文件内容的排序、将各项约定付诸实践的 buf lint 规则名称、基于通道与基于发布的版本演进方式,以及弃用机制。
3. 破坏性变更门禁
Protobuf 编码只能保证线路兼容性,不能保证客户端代码兼容性(AIP-180 对此作了区分),因此门禁必须依靠工具,而非审阅者保持警惕:
- 每个 PR 都运行
buf breaking --against <main>,将其设为 CI 硬性门禁,并使用 STANDARD 规则集运行buf lint。对于公共接口,默认采用最严格的规则类别(FILE);它能检测到按包检查会放过的生成代码导入中断问题。通过发布基线和审批记录,将门禁发现的问题整理成面向合作伙伴的变更日志,可使用samber/developer-platform-skills@api-changelog-automation。 - 了解工具能捕捉而人工审阅者容易忽略的陷阱:
- 重命名在语义上等同于删除后新增(始终属于破坏性变更)。
- 将字段移入或移出
oneof会破坏生成的 Go 存根。 - 将消息移到另一个文件会破坏生成代码的导入;文件路径属于契约的一部分。
- buf 留下的盲区:
buf breaking不会检查google.api.http等自定义选项,因此团队可能破坏面向 REST 的 URL/动词映射,而所有 proto 门禁仍显示通过。应添加专门的检查:对注解派生的 HTTP 接口(路径、动词、正文映射)建立快照,并在 CI 中进行差异比较;或者对转码后的路由进行契约测试。这是一种明确的故障模式,而非理论上的风险。 - 在版本边界两侧进行测试:旧客户端连接新服务端,以及新客户端连接旧服务端。“架构能否解析”并不等于“跨版本 RPC 是否成功”。
- 当公共接口规模足以需要人工兜底时,改用 Buf Schema Registry 审查流程:破坏性变更的推送会进入审批/拒绝队列,并留下记录,这是 proto 原生的审查委员会门禁。不使用 buf 的团队可针对已提交到代码库的
proto.lock使用 Salesforce 的proto-backwards-compat-maven-plugin。
弃用机制也原生支持 proto:设置 deprecated = true(适用于消息、枚举、枚举值和服务),并添加 AIP-192 注释,说明弃用原因及替代方案。不同发布渠道的要求差异很大:
- Alpha 版本可能会在不另行通知的情况下消失。
- Beta 版本建议弃用 180 天后再移除。
- 对稳定组件进行原地破坏性变更是“极端的做法”,仅适用于安全或法规要求。
通知期限本身属于 samber/developer-platform-skills@api-versioning-policy 的范畴。
4. 流式策略:默认使用一元调用
gRPC 的四种调用类型,在公共接口上的成本并不相同。默认公开一元 RPC;每个流式方法都必须经过审慎决策并记录在案,且接受其成本——绝不能把它当作免费的功能。
- 服务端流式是存在真实推送/持续获取用例时,首先考虑的流式模式:它可以通过网关无缝映射到 SSE,也能映射到 Connect 的流式编码。通知、日志持续获取、渐进式结果。
- 客户端流式和双向流式会给外部使用者带来明确成本:Microsoft 自己的指南警告说,“出于性能原因用双向流式替代一元调用是一种高级技巧,并不适用于许多场景”。
- 流在传输部分数据后中途失败,因此每个外部 SDK 使用者都需要处理重启/恢复记录,而一元重试完全不需要这些工作。
- 重试不再能由客户端库透明管理。
- 浏览器完全无法通过 HTTP/1.1 使用客户端流式或双向流式——这是协议限制,不是工具缺失(通过 HTTP/2 使用 Connect 是例外)。
- 流式传输会削弱负载均衡效果:在 L4 负载均衡器下,HTTP/2 多路复用会在连接的整个生命周期内,将客户端的所有流固定到同一个后端。公共 gRPC 边缘需要 L7、支持 HTTP/2 的负载均衡,以及低于负载均衡器空闲超时的客户端 keepalive 间隔——具体厂商的超时数值见 references/public-grpc-case-studies.md。
- AIP-127 要求每个 RPC 都必须有 HTTP 映射,双向流式除外,因为 HTTP/1.1 无法承载它——因此,每个双向流式方法也都需要记录在案的非流式替代方案,否则它在转码后的接口中将不可见。
落实这一决策,而不只是记录下来:当接口确定只使用一元调用时,启用 buf 的 UNARY_RPC lint 类别,以防未来的 PR 悄然引入网关、SDK 或传输方式无法承载的流式方法。同系列的 samber/developer-platform-skills@api-idempotency-retry 负责重试机制、截止时间传播和退避泛型;此步骤只决定公共契约提供哪些调用形式。
5. 错误模型:google.rpc.Status 机制
同级项目 samber/developer-platform-skills@api-error-design 负责分类理念——代码目录、消息编写、可重试性信号。本步骤负责 gRPC 原生机制,以及会影响公共接口的两个陷阱:
- 使用
google.rpc.Status:code:17 个标准代码之一。message:面向开发者的英文文本,绝不使用本地化的用户文本。details:来自google/rpc/error_details.proto的类型化补充信息(优先使用ErrorInfo;字段违规使用BadRequest;RESOURCE_EXHAUSTED搭配RetryInfo)。
- 返回最具体的适用代码(同时适用时,选
OUT_OF_RANGE而非FAILED_PRECONDITION)。出于防御习惯,默认把所有错误都归为UNKNOWN/INTERNAL是已明确指出的反模式:这会把状态仪表板上的所有状态都压成同一类。 - 在结构层面清理出站错误,而不只是清理文本:文档说明
DebugInfo仅供内部使用——响应发出前,应从details中将其过滤;仅清理message并不足够。 - 陷阱一——映射表的方向。 gRPC 项目自己的文档明确指出:“服务端不得使用此表来确定要使用的 HTTP 状态码……这些映射既不对称,也非一对一。”标准 gRPC↔HTTP 映射表供客户端解读未附带
grpc-status的响应;将错误转换后向外返回的网关需要制定自己的映射,并根据实际使用的转码实现进行确认。 - 陷阱二——HTTP 会抹平差异。 在常见的网关映射中,三个代码(
INVALID_ARGUMENT、FAILED_PRECONDITION、OUT_OF_RANGE)最终都会映射为 400,而CANCELLED则映射为非标准的 499。应告知使用者,HTTP 状态行会丢失信息,正文中的结构化信封才是事实依据。 - 验证信封能否通过网关:
- Envoy 需要设置
convert_grpc_status: true,并确保 proto 描述符中包含所有详情类型(缺少的类型会被静默丢弃)。 - Connect 原生以 JSON 序列化错误。
- grpc-gateway 的默认处理程序会将消息压平并完全丢弃
details——如果结构化详情很重要,则必须使用自定义错误处理程序。
- Envoy 需要设置
通常只有 UNAVAILABLE 无需额外信号即可安全自动重试(AIP-194);其他情况都需要明确的 RetryInfo 或由调用方自行判断。完整的 17 个代码表、网关映射、详情目录和各网关的保留机制见 references/grpc-error-http-mapping.md。
6. 转码与网关架构
此步骤要做出的设计决策是:面向非 gRPC 消费者的边缘服务由什么提供,以及如何表达映射——AIP-127 的 google.api.http 注解是所有实现最终采用的惯例(“除双向流式 RPC 外,API 必须为每个 RPC 提供 HTTP 定义”)。选项按优先级排列:
- 工作量:
raw public gRPC edge > grpc-gateway == Envoy transcoder > Connect-RPC - 价值:
Connect-RPC > Envoy transcoder > grpc-gateway > raw public gRPC edge - 效率:
Connect-RPC > Envoy transcoder > grpc-gateway > raw public gRPC edge
这里的工作量指团队需要运维和重新生成的内容;价值指每份 proto 契约能触达的受众,同时保留错误和流式传输保真度。grpc-gateway == Envoy 在工作量上的并列是真实存在的:每次 proto 变更都重新生成 Go 代理,与保持描述符集和过滤器配置同步,属于不同工作,但量级相当——而“你已经在运行 Envoy”恰恰是打破平局的条件。
- 默认选项:Connect-RPC。 一个服务端同时支持 Connect、gRPC 和 gRPC-Web:
- 无需代理。
- 原生支持浏览器。
- 通过 HTTP/2 完整支持流式传输。
- 开箱即用地以 JSON 返回错误。
- 与 gRPC 在线路上兼容(已通过 Google 的互操作测试套件验证)。
它于 2024 年 4 月进入 CNCF Sandbox,目前已在 CrowdStrike、PlanetScale、RedPanda、Chick-fil-A、Bluesky 和 Dropbox 投入生产使用。Buf 在推出时这样阐述:“从概念上讲,gRPC 协议就是采用 Protobuf 编码消息体的 HTTP”——对于大多数新的服务接口,Connect 消除了选择网关的决策。
- 当 Envoy 已经是你的网格数据平面,而新增一个运行时才是真正的成本时,优先选择 Envoy 的 gRPC-JSON 转码器——它由描述符驱动,无需生成胶水代码,是 Kubernetes 环境中的常见做法。选择它并非因为 Envoy 较差;“你已经在运维它”是合理的理由。
- 如果现有的 Go 投入已经包含 grpc-gateway 和自定义错误处理器,就继续使用 grpc-gateway;它需要一个代码生成步骤,并且每个请求都要进行一次 JSON↔protobuf 双重解析,而它的默认错误处理在三者中最弱(步骤 5.6)。
- **原始公有 gRPC 边缘是资源最受限的选项:**保真度最高(端到端二进制传输、完整流式传输、零转码损耗),工作量也最高(需要支持 gRPC 的边缘层,具备 L7 负载均衡、WAF 和 TLS 终止——Cloudflare 将其作为产品提供——还要全面审查内部 RPC 的对外暴露情况,并要求每个消费者都具备 Protobuf 工具链)。它在每轮效率比较中都落败;唯一会让它反而成为优先选项的条件,是步骤 1 中确认存在由 SDK 驱动的控制平面受众,从而触发 Temporal 方案。即便如此,也要像 Temporal 一样,同时发布 HTTP 接口。
- **排除而非降级:**当问题 3 的回答是浏览器客户端直接调用时,将原始公有 gRPC 作为唯一接口。浏览器在结构上无法使用 gRPC 帧格式;将这个选项留在菜单底部,会让它悄然重新进入范围。将其删除,并从以上三个选项中选择。
此排名是默认建议,并非硬性规定。请根据问题 6 和你对团队的了解重新排序:
- 精通 Envoy 的平台团队几乎可以不费力地采用转码器。
- 交付期限紧迫时,应优先选择团队已经在运维的方案。
- 多个产品将在未来数年共用的契约,应优先考虑错误保真度(价值维度),而非本季度的工作量。
无论选用哪个方案,性能关键型消费者都应采用原生 gRPC 或 Connect 的二进制模式——每条 JSON 转码路径都会产生实际的解析开销。
机制表(各选项对流式传输的支持、浏览器访问路径和代理要求)及引述来源:references/public-grpc-case-studies.md。
7. 外部身份验证、TLS 与暴露面审计
依赖内部身份验证的想法并不合适:mTLS 用于验证_工作负载_,在网格内部扩展也没有问题,但为素不相识的开发者签发和吊销客户端证书,在运维上并不现实。公共边缘验证的是应用和用户,而不是工作负载——网格并未消失,只是从再往里一跳的地方开始。操作顺序如下:
- 首先启用 TLS,这一点不可妥协:凭据通过 gRPC 元数据传输;没有传输安全保护时就是明文。大多数实现根本不会通过未加密的通道发送凭据。
- 根据调用方类型选择 OAuth2 流程:机器/服务调用方使用 Client Credentials;需要用户交互式身份验证时使用 Authorization Code + PKCE。将令牌作为
authorization: Bearer <token>元数据传递,并在服务器拦截器中验证。 - 令牌机制:
- 使用 JWT 作为令牌格式,采用强签名(RS256),并包含过期声明。
- 针对授权服务器执行令牌内省,并缓存结果,避免每次调用都增加其负载。
- 外部调用方数量达到足以支撑采用成熟身份提供商的程度后,使用成熟的身份提供商,而不是自行实现发行方。
- 在方法级别强制执行作用域——不要只检查“此调用方是否已通过身份验证”,还要检查“此令牌是否具有调用此 RPC 的作用域”。
- API 密钥只能作为身份验证的补充,绝不能取代身份验证(这是 Google 自身 Endpoints 的区分方式):密钥用于标识项目/使用方,以便归属配额并进行粗粒度访问控制,而不是用来表示经过身份验证的身份。
- 超出配额时,速率限制应返回
RESOURCE_EXHAUSTED(转码后为 429),并附带RetryInfo详情,让调用方退避,而不是不断冲击同一限制。 - 暴露面审计是所有内部优先服务的必做项:在生产环境中禁用服务器反射(端口公开后,它会成为攻击者用于发现 API 的工具),然后全面梳理所有方法,找出那些从未设计为对外开放的管理、调试和监控 RPC。即使已启用 TLS 和身份验证,这个漏洞也不会因此消失。
参考架构图应包括:在公共网关(Apigee、Cloudflare、Envoy 均为厂商实例)处执行 TLS 终止、令牌验证、逐方法授权和速率限制;网关前接内部网格,mTLS 在网格中恢复。
故障模式
反模式检查清单——以下每一项都属于直接审计发现:
- 服务器或网关根据 gRPC 项目明确禁止服务器使用的客户端 gRPC↔HTTP 映射表推导 HTTP 状态码。
buf breaking检查通过,但google.api.http注解的变更破坏了公开 REST 映射——这是没有专门检查手段的盲点。- 在生产环境中使用 grpc-gateway 默认错误处理程序,导致所有
details负载都被静默丢弃。 - 在可从公网访问的服务上启用了服务器反射。
- 两个 RPC 共享同一个请求或响应消息;请求类型使用裸标量。
- proto 文件名中包含版本号,或目录结构与包名不一致。
- 在面向浏览器的接口中添加了流式方法,却没有提供非流式替代方案,也没有记录权衡决策。
- 所有故障都返回
UNKNOWN或INTERNAL;DebugInfo泄露给外部调用方。 - 在流式 RPC 前放置 L4 负载均衡器,导致每个客户端的流都固定连接到同一个后端。
- 客户端 keepalive 间隔长于负载均衡器的空闲超时时间,导致负载均衡器在 keepalive 生效前就断开连接。
- 在
v1包中发布 Beta 功能。
衡量标准
通过门槛根据上述来源规则自行设定(此领域不存在行业标准阈值;每项门槛均为二元且可审计):
- 破坏性变更门槛:除新主版本外,默认分支中不得出现任何破坏性 proto 变更——CI 中的
buf breaking(FILE 类别)在 100% 的合并中均通过。 - 注解覆盖率:所有带有
google.api.http注解的 RPC 均由专门的映射差异检查或契约测试覆盖,因为 buf 不会检查这些注解。 - 流式处理规范:仅支持一元调用的接口启用
UNARY_RPClint;或者,为每个流式方法记录一项已接受权衡的决策,并且(对于双向流)提供一个非流式替代方案。 - 暴露范围:生产环境中禁用反射,并在发布前完成内部 RPC 审计——两项均为二元门槛。
反复迭代设计,直至四项门槛全部通过。之后,将以下指标作为趋势观察(而非门槛):由转码错误引发的支持工单占比,以及每次发布的跨版本兼容性测试结果。
调用示例
- “我们的平台团队想向合作伙伴开放内部 gRPC 服务——请设计公开接口,并告诉我们这样做是否合适。”
- “请为我们准备公开发布 proto 的公共 API 设计 proto 包和版本控制约定,并设置 CI 门槛以防止破坏性变更。”
- “我们正在为浏览器客户端的 gRPC 后端部署 Connect-RPC——请审查错误模型和转码架构。”
- “在向外部开发者开放这个 gRPC 服务之前,请对它进行审计。”
参考资料
- references/proto-governance-reference.md - 详细介绍 AIP 文件/包规则、buf lint 规则名称、AIP-180 兼容性陷阱、渠道与发布版本控制,以及弃用机制。
- references/grpc-error-http-mapping.md - 17 个规范代码、包含折叠点的完整网关 HTTP 映射、错误详情目录,以及各网关保留信封的机制。
- references/public-grpc-case-studies.md - Google、Square、Dropbox、Cloudflare、Temporal 案例研究及其精确性注意事项;转码选项机制表;Connect-RPC 采用情况;负载均衡器 keepalive 数值。
另请参阅同一集合中的条目:
samber/developer-platform-skills@api-integration-surface-strategy- 决定究竟要提供哪些接口的总体决策;此技能会重新验证其中的 gRPC 分支并执行该决策。samber/developer-platform-skills@public-api-design-review- 对 REST/JSON 侧进行全接口一致性审查;将 gRPC 专属设计交由此处处理。samber/developer-platform-skills@public-graphql-api-design- 公共 GraphQL 接口的结构类比;采用相同的门槛优先结构,但范式不同。samber/developer-platform-skills@api-versioning-policy- 通知期限、日落沟通和通用治理规范;此技能仅负责 gRPC 原生版本编码和门槛。samber/developer-platform-skills@api-error-design- 错误分类理念、消息编写和可重试性信号;此技能仅负责google.rpc.Status机制和 HTTP 映射陷阱。samber/developer-platform-skills@api-idempotency-retry- 客户端重试机制、截止时间传播和退避通用规范,供第 4 步的流式处理决策使用。