接口是服务之间的契约
一个微服务写好接口,几十个调用方在背后用。你随手改个字段名,可能第二天半夜就有线上告警。API 之所以重要,是因为它不是你一个人的代码,而是你和所有调用方之间的一份承诺。
好的 API 设计,让调用方用得顺、提供方改得动;坏的 API,则会在每一次迭代里反复制造线上事故。
改接口的代价,从来不只在你这一行——它要算上所有调用方跟着改的成本。
本文核心知识点
- 契约接口是双方共同遵守的承诺。
- 资源建模用名词表达资源,用动词表达操作。
- 契约文档让双方有共同依据。
- 版本演进时不破坏老调用方。
- 向后兼容新增字段是安全的,删改字段是危险的。
先想清楚:这个接口到底干什么
设计接口最忌讳边写边想。动手之前先回答几个问题:这个接口给谁用?输入什么、输出什么?失败时调用方该怎么办?
| 要想清楚 | 为什么 |
|---|---|
| 调用方是谁 | 不同调用方需要的字段不同 |
| 核心输入输出 | 避免接口越做越胖 |
| 失败语义 | 调用方需要知道怎么处理错误 |
| 性能预期 | 同步还是异步、要不要分页 |
把这些想清楚,接口的形状自然就出来了,而不是写着写着变成什么都往里塞的大杂烩。
资源建模:用名词而非动词
一套直观的约定是:路径表达资源(名词),方法表达操作(动词)。这样看到路径就知道操作的是什么,看到方法就知道要做什么。
# 资源用名词,操作用方法
GET /orders 查订单列表
POST /orders 创建订单
GET /orders/{id} 查单个订单
PUT /orders/{id} 更新订单
DELETE /orders/{id} 删除订单
# 不要把动作塞进路径里,读起来会很别扭。
路径保持简洁一致,调用方不用记一堆命名不一的接口,猜都能猜个八九不离十。
契约:让双方有共同依据
接口一旦被别人用,就得有一份双方都认的说明:参数有哪些、类型是什么、哪些必填、返回长什么样、错误码什么意思。
| 契约里该写清 | 例子 |
|---|---|
| 请求参数 | 字段名、类型、是否必填 |
| 响应结构 | 成功返回什么、分页怎么给 |
| 错误码 | 每种错误对应什么含义 |
| 版本与变更 | 这次改动影响谁 |
契约最好能被工具自动校验,避免「文档写一套、实际跑一套」的对不上。
版本管理:演进不破坏老用户
接口一定会随业务演进。关键是:演进的时候,已经在用的老调用方不能突然挂掉。
# 向后兼容的基本规矩
- 新增可选字段:安全,老调用方忽略即可
- 删除或改名字段:危险,老调用方会挂
- 必须破坏时:开新版本,老版本保留过渡期
# 把「破坏」当成例外,而不是日常。
好的接口版本策略,是让老用户无感地继续用,让新用户用上更好的。
错误与兼容:细节里见功夫
很多接口事故都出在细节上:错误码含糊、字段该必填却给了空、同名参数含义偷偷变了。这些都需要在契约和评审里盯住。
- 错误信息要让调用方能据此处理,而不是一句笼统的失败。
- 新增字段永远设成可选,别强制老调用方立刻适配。
- 同名字段的含义不要在版本里悄悄改变。
这些细节做好了,接口才真正称得上「好用又稳」。
让接口越用越顺
API 设计与版本管理的最终目的,是让服务之间的协作不随系统长大而变得痛苦。
- 清晰的资源建模让接口好猜好记。
- 契约让双方不用反复口头对。
- 版本策略让每次演进都平滑安全。
当服务之间讲的是同一种话,系统就不会因为拆得越细、接口越多而越难管理。