Google Cloud API 设计指南
Google Cloud API设计指南是自2014年起在Google内部使用的网络API通用设计指南,适用于REST和RPC(特别是gRPC)API。本指南强调资源导向设计、一致性和可维护性,帮助开发者创建高质量、易用且符合Google标准的API。
一、核心设计原则
1. 资源导向设计(Resource-Oriented Design)
API的核心抽象是资源(名词),而非操作(动词)。资源以层次结构组织,通过标准方法(HTTP动词或RPC方法)进行操作。
-
资源是API的基础
:每个资源都有唯一的资源名称作为标识符
-
资源层次结构
:如
publishers/{publisher_id}/books/{book_id},反映资源间的父子关系 -
集合资源
:表示同类资源的容器,如
publishers/{publisher_id}/books -
标准方法优先
:尽量使用标准方法(Get、List、Create、Update、Delete),仅在必要时使用自定义方法
2. 一致性(Consistency)
API应在命名、结构、错误处理和行为上保持一致,降低用户学习成本。
-
使用相同的命名约定、数据格式和错误模型
-
遵循标准的分页、过滤和排序机制
-
保持方法签名和响应格式的一致性
3. 简单性(Simplicity)
API应易于理解和使用,避免不必要的复杂性。
-
设计直观的资源模型和API接口
-
提供清晰的文档和示例
-
隐藏内部实现细节,暴露简洁的抽象
4. 可扩展性(Extensibility)
API应能在不破坏现有用户的情况下演进。
-
使用版本控制机制处理不兼容变更
-
为消息字段预留编号空间
-
支持向后兼容的扩展方式
5. 性能与可靠性(Performance & Reliability)
API应设计为高性能、可靠且具有容错能力。
-
支持异步处理长时间运行的操作
-
实现合理的缓存策略
-
提供适当的错误重试机制
二、资源命名规范(AIP-122)
资源名称是API中最重要的概念之一,必须唯一标识资源并反映其层次结构。
|
规则
|
说明
|
示例
|
| --- | --- | --- |
| 唯一性 |
资源名称在API范围内必须唯一
| publishers/123/books/456 |
| 层次结构 |
使用/分隔符表示资源间的父子关系
| publishers/{publisher_id}/books/{book_id} |
| 集合命名 |
集合资源使用复数小写形式
| books
而非book或BookCollection
|
| 资源ID |
资源ID应使用小写字母、数字和连字符
| my-book-123
而非MyBook123
|
| 原子性 |
资源名称是原子字符串,客户端不应解析其结构
|
客户端应将资源名称视为不透明字符串
|
| 完整路径 |
资源名称必须是完整路径,包含所有父资源ID
|
避免使用相对路径
|
三、标准方法(AIP-130至AIP-135)
Google定义了5种标准方法,覆盖大多数资源操作场景,提供一致的API体验。
1. Get方法(AIP-131)
-
作用
:获取单个资源的详细信息
-
RPC签名
:
rpc GetBook(GetBookRequest) returns (Book) -
HTTP映射
:
GET /v1/{name=publishers/*/books/*} -
请求参数
:必须包含资源名称
name字段 -
响应
:返回请求的资源对象
2. List方法(AIP-132)
-
作用
:获取资源集合的列表
-
RPC签名
:
rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) -
HTTP映射
:
GET /v1/{parent=publishers/*}/books -
分页支持
:使用
page_size和page_token参数 -
过滤与排序
:支持
filter和order_by参数 -
响应结构
:包含
books[]资源数组和next_page_token
3. Create方法(AIP-133)
-
作用
:创建新资源
-
RPC签名
:
rpc CreateBook(CreateBookRequest) returns (Book) -
HTTP映射
:
POST /v1/{parent=publishers/*}/books -
请求体
:包含要创建的资源对象
-
响应
:返回创建的资源对象,包含完整资源名称
4. Update方法(AIP-134)
-
作用
:更新现有资源
-
RPC签名
:
rpc UpdateBook(UpdateBookRequest) returns (Book) -
HTTP映射
:
PATCH /v1/{book.name=publishers/*/books/*} -
请求体
:包含要更新的资源对象
-
更新方式
:使用部分更新(PATCH)而非全量更新(PUT)
-
乐观锁
:支持
update_mask和etag字段进行并发控制
5. Delete方法(AIP-135)
-
作用
:删除资源
-
RPC签名
:
rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty) -
HTTP映射
:
DELETE /v1/{name=publishers/*/books/*} -
响应
:成功时返回空响应
-
软删除支持
:可选支持
force参数进行永久删除
四、自定义方法(AIP-136)
当标准方法无法满足需求时,可使用自定义方法,但应遵循以下规范:
1. 命名与签名
-
方法名称使用动词+名词形式,如
BatchDeleteBooks、MoveBook -
RPC签名:
rpc CustomMethod(CustomMethodRequest) returns (CustomMethodResponse) -
HTTP映射:
-
自定义操作:
POST /v1/{resource=path/*}:customMethod -
资源操作:
POST /v1/{name=path/*}/customMethod
2. 使用场景
-
执行复杂业务逻辑(如批量操作、数据转换)
-
实现标准方法无法覆盖的操作(如移动资源、批准请求)
-
处理非CRUD操作(如计算、验证)
3. 最佳实践
-
仅在标准方法不适用时使用自定义方法
-
保持自定义方法的数量最少
-
遵循与标准方法一致的错误处理和响应格式
五、API版本控制(AIP-185)
版本控制是管理API演进的关键机制,确保变更不会破坏现有用户。
1. 版本类型
-
主版本(Major Version)
:包含不兼容变更,如
v1、v2 -
次版本(Minor Version)
:仅包含向后兼容的变更,通常不显示在URL中
-
预发布版本(Pre-release Version)
:如
v1alpha1、v1beta1,用于早期测试
2. 版本标识
-
URL路径中包含主版本号:
/v1/publishers -
Protobuf包名包含版本号:
package google.example.library.v1 -
预发布版本应在版本号后添加后缀:
v1alpha1、v1beta2
3. 版本兼容性规则
-
主版本变更
:允许不兼容变更,但必须提供迁移路径
-
次版本变更
:必须保持向后兼容,包括:
-
新增字段(不会影响现有客户端)
-
新增可选参数
-
新增枚举值(客户端应处理未知值)
-
预发布版本
:不保证向后兼容性,可频繁变更
六、错误处理(AIP-193)
API错误处理应提供清晰、一致且有用的错误信息,帮助用户快速诊断和解决问题。
1. 错误模型
-
使用
google.rpc.Status消息作为错误响应 -
包含三个核心字段:
-
code:标准错误码(如
INVALID_ARGUMENT、NOT_FOUND) -
message:人类可读的错误描述
-
details:附加错误信息(如参数验证错误、资源冲突详情)
2. 标准错误码
Google定义了一套标准错误码,应优先使用而非自定义错误码:
|
错误码
|
HTTP状态码
|
说明
|
| --- | --- | --- |
| OK |
200
|
成功
|
| INVALID_ARGUMENT |
400
|
请求参数无效
|
| NOT_FOUND |
404
|
资源不存在
|
| PERMISSION_DENIED |
403
|
权限不足
|
| UNAUTHENTICATED |
401
|
未认证
|
| RESOURCE_EXHAUSTED |
429
|
资源耗尽(如配额限制)
|
| INTERNAL |
500
|
服务器内部错误
|
| UNAVAILABLE |
503
|
服务不可用
|
3. 错误信息最佳实践
-
错误信息应具体、明确,避免模糊描述
-
提供可操作的建议,帮助用户解决问题
-
不要暴露内部实现细节(如堆栈跟踪)
-
使用一致的错误格式和语言
七、数据类型与字段设计(AIP-148)
1. 标准字段
API应使用标准字段名称和类型,提高一致性和可理解性:
|
字段名称
|
类型
|
用途
|
| --- | --- | --- |
| name | string |
资源唯一标识符
|
| display_name | string |
人类可读的资源名称
|
| create_time | google.protobuf.Timestamp |
资源创建时间
|
| update_time | google.protobuf.Timestamp |
资源最后更新时间
|
| etag | string |
乐观锁版本标识
|
| labels | map<string, string> |
资源标签
|
2. 字段设计最佳实践
-
使用驼峰命名法(snake_case):
user_name而非UserName或USER_NAME -
为字段分配永久编号:一旦发布,字段编号不得更改
-
标记输出-only字段:如
create_time、update_time -
使用适当的数据类型:
-
时间:
google.protobuf.Timestamp -
持续时间:
google.protobuf.Duration -
货币:
google.type.Money -
枚举:使用Protobuf枚举类型,避免字符串常量
八、分页、过滤与排序
1. 分页(AIP-158)
-
使用
page_size和page_token参数控制分页 -
响应包含
next_page_token,为空表示没有更多结果 -
推荐默认
page_size为100,最大不超过1000 -
示例:```
messageListBooksRequest{
string parent = 1;
int32 page_size = 2;
string page_token = 3;
}messageListBooksResponse{
repeated Book books = 1;
string next_page_token = 2;
}
2. 过滤(AIP-160)
-
使用
filter参数支持复杂过滤条件 -
过滤语法:字段名+运算符+值,支持逻辑运算符
AND、OR、NOT -
示例:
filter: "author = 'John Doe' AND publish_date > '2020-01-01'"
3. 排序(AIP-161)
-
使用
order_by参数指定排序字段和方向 -
排序语法:字段名+
asc/desc,多个字段用逗号分隔 -
示例:
order_by: "publish_date desc, title asc"
九、长时间运行的操作(LRO,AIP-151)
对于耗时超过60秒的操作,应使用长时间运行的操作模式:
1. 操作流程
-
客户端发送请求
-
服务端立即返回
Operation对象,包含操作ID和状态 -
客户端通过
GetOperation方法轮询操作状态 -
操作完成后,
Operation对象包含结果或错误
2. 实现示例
rpc ImportBooks(ImportBooksRequest) returns (google.longrunning.Operation) {
option (google.api.http) = {
post: "/v1/{parent=publishers/*}/books:import"
body: "*"
};
option (google.longrunning.operation_info) = {
response_type: "ImportBooksResponse"
metadata_type: "ImportBooksMetadata"
};
}
十、最佳实践总结
-
优先使用标准方法
,保持API一致性
-
设计清晰的资源模型
,反映业务领域
-
使用一致的命名和格式
,降低用户学习成本
-
实现严格的错误处理
,提供有用的错误信息
-
规划API版本策略
,支持平滑演进
-
优化性能
,支持异步处理和缓存
-
提供完整的文档
,包括示例和使用指南
-
遵循AIP规范
,确保与Google Cloud API生态系统的兼容性

浙公网安备 33010602011771号