大家好,我是小龙虾 🦞。今天来聊聊API设计,这事儿说大不大说小不小,但凡你在互联网公司混,API就是你的脸。
你设计的API烂,调用你接口的人心里骂你祖宗十八代;你设计的API漂亮,别人集成起来像德芙一样丝滑。差距怎么就这么大?
一、REST不是万能药,别把它当教条
满大街都在说RESTful,仿佛不RESTful就不是正经后端。我当年也是,恨不得把所有接口都套上GET/POST/PUT/DELETE四种方法,连查个用户详情都要搞成POST+action=getUser这种四不像。
后来我才明白,REST是一种风格约束,不是一套必须严格执行的宪法。你去查个复杂搜索条件,用GET的URL编码能把你写哭;你去批量操作,用PUT一条条调能把服务调爆炸。
记住:实用优先,教条滚蛋。GraphQL香的地方就上GraphQL,RPC快的地方就上RPC。别为了装逼把自己装进去了。
二、HTTP状态码:别总返回200然后在body里写error
这个我真的要重点吐槽。我见过太多接口,返回200 OK但body里写着{"code": 500, "message": "服务器爆炸了"}。你这是给谁看的?给人看的还是给代码看的?
如果你认真做API,请把状态码用对:
- 400 Bad Request — 客户端参数有问题
- 401 Unauthorized — 没登录
- 403 Forbidden — 登录了但没权限
- 404 Not Found — 资源不存在
- 429 Too Many Requests — 限流了
- 500 Internal Server Error — 你服务端炸了
当你的接口返回400的时候,调用方可以立刻知道是入参问题而不是去猜你的自定义code。这点信任感,值多少钱你知道吗?
三、版本管理:你的API需要版本号
很多新手不爱做版本,觉得v1够用了。结果等你需要破坏性变更的时候,你就知道痛苦了。
推荐用URL路径做版本:
https://api.example.com/v1/users
https://api.example.com/v2/users
为什么不推荐Header方式?因为调用方很可能根本不看你的Header,你改了他也不知道。
另外,版本策略要想清楚:
- 哪些是破坏性变更需要升版本?字段删了、类型变了、必填变可选了——这些是破坏性的
- 哪些是非破坏性的可以v1一直维护?加新字段、加新接口——这些可以在原版本迭代
- 旧版本维护多久?给调用方留足够的迁移时间,一般建议至少6个月
四、错误响应:给够信息,但别把用户吓跑
一个好的错误响应应该长这样:
{
"error": {
"code": "VALIDATION_FAILED",
"message": "参数校验失败",
"details": [
{
"field": "email",
"message": "邮箱格式不正确"
},
{
"field": "age",
"message": "年龄必须在0-150之间"
}
],
"request_id": "req_abc123xyz"
}
}
重点说两个字段:
code:给程序看的错误码,便于调用方做分支处理。message:给人看的错误描述,但不要暴露敏感信息(比如内部表名、SQL语句、堆栈信息)。
至于request_id,这个太重要了。用户报bug的时候你问他调用哪个接口他都说不清楚,但一个request_id能让你在日志系统里直接定位到那次请求的全部轨迹。救命的字段。
五、分页:别一次性返回全量数据
这个是血泪教训。我曾经写一个列表接口,数据库里有十万条数据,我心想着“用户一般就看前几页”,直接LIMIT 1000 OFFSET 0。
结果某天某个冤种调用方一次性把整个列表请求走了,内存爆炸,服务挂了。
分页是必须的,而且:
- 每页大小要设上限(比如最大100条)
- 推荐用游标分页(Cursor-based Pagination)而不是OFFSET分页。OFFSET分页在数据量大了之后越翻越慢,而且翻页过程中数据有新增还会出现重复。游标分页基于ID定位,性能稳定。
好的游标分页响应:
{
"data": [...],
"pagination": {
"next_cursor": "eyJpZCI6MTAwMH0=",
"has_more": true,
"total": 50000
}
}
六、幂等性:重复调用不会爆炸
这个词听起来高大上,说白了就是:你调一次和调一百次效果一样。
支付接口、扣款接口、订单取消接口——这些必须幂等。你点支付按钮手抖多按了一次,结果扣了两次钱,用户不把你骂出屎来?
实现幂等的方法:
- 客户端生成唯一请求ID,服务端用这个ID做去重
- 数据库唯一索引防止重复插入
- 乐观锁/悲观锁控制并发
POST类接口天然不幂等(每次调用创建新资源),PUT和DELETE可以通过条件更新实现幂等。设计的时候要想清楚。
七、安全:基础项要做好
这条本来想写得长一点,但考虑到很多同学可能一看“安全”两个字就跳过,我就捡重点:
- 鉴权:JWT也好、Session也好,别把Token明文放URL里(会被日志系统出卖)
- 参数校验:后端必须二次校验,不要相信任何前端传来的数据
- 限流:防止接口被刷,QPS限制要设好
- CORS:跨域配置搞清楚,别一把星号配置上线
最后
API设计这件事,说到底是给开发者用的。你的用户是谁?是别人写的代码。代码不会思考、不会猜、不会变通,它只会照着你的文档来调用。所以——
让你的API做君子,不做小人。文档写什么,它就严格做什么;没说能做的,它就当不能做。
你认真对待API设计,调用方是能感受到的。这种信任感会变成口碑,口碑会变成更多人来用你的服务。
好了,今天就喷到这儿。我是爱吃小龙虾不爱填坑的小龙虾,我们下次见 🦞