在生产环境中让你后悔的8个API设计错误

发布: (2026年3月30日 GMT+8 08:19)
8 分钟阅读
原文: Dev.to

Source: Dev.to

API 是永久性的。听起来很戏剧化,直到你花了三周时间在十四个客户端团队之间协调一次破坏性更改,同时在一个没人想维护的兼容性垫片中保持旧端点的可用。糟糕的代码可以悄悄重构。糟糕的 API 合约是一种公共债务,会在每个季度复利增长。

以下是八种从当时看似合理、已上线生产却最终带来真实痛苦的设计模式。

Mistake 1: Not Versioning From Day One

对提前进行版本控制的反对意见听起来很合理——因为你还不知道会有什么变化。问题在于,一旦有任何外部客户端进入生产环境,“以后”就立刻到来了。此时,添加版本控制不仅是一个决定,而是一次迁移。

URL 路径版本化(/v1/users/v2/users)是最直观的做法,也是大多数团队的默认正确选择。它在基础设施层面易于路由,并且在任何日志文件中都能清晰可见。Stripe 之所以采用这种方式,原因就在于它的清晰性,这也是 Stripe 的 API 被认为是业界最佳设计之一的关键因素。

错误 2:命名约定不一致

在同一个 API 中混用 camelCasesnake_case 是文档债务。它迫使使用者通过反复试验来解决歧义。约定的选择不如一致性重要——选定一种并在序列化层强制执行,而不是仅靠约定和希望。

Mistake 3: Returning Too Much Data by Default

一个返回资源所有已知信息的端点看似慷慨,实际上却是性能负担。当你的 /users/{id} 同时返回个人资料、偏好设置、账单历史和活动日志时,每个移动客户端都要为这些随后被丢弃的数据付出序列化的代价。

N+1 问题是相关的陷阱:如果 /orders 端点为每个订单获取完整的客户对象,它会为订单列表执行一次查询,然后为每个订单再执行一次查询来获取客户信息。分页应当是默认行为,而不是可选项——对于时间序列数据,基于游标的分页比基于偏移的分页更可靠。

错误 4:错误的错误响应

一个没有正文的通用 500 响应实际上是缺乏信息却伪装成响应。Stripe 的错误格式是值得效仿的标准:HTTP 状态码、机器可读的 code 字段、人类可读的消息,以及足够的上下文来重现问题。验证错误应指明哪些字段失败以及原因,而不仅仅是 “validation failed.”

错误 5:没有速率限制

没有速率限制的 API 等同于邀请无意的拒绝服务攻击。带有错误重试循环的客户端可能会导致你的服务对所有人不可用。滑动窗口计数器算法是正确的默认选择:它在保持固定窗口内存效率的同时,近似完整滑动日志的准确性。将在响应头中暴露限制(X-RateLimit-RemainingRetry-After),以便行为良好的客户端能够进行相应调整。

错误 6:忽视幂等性

网络请求可能以与成功无法区分的方式失败。超时——服务器在响应失败之前是否已经处理了请求?对于写操作,盲目重试可能导致重复收费或状态不一致。Stripe 要求对所有修改金融数据的 POST 请求使用幂等性键。 在拥有外部客户端之前就实现它们,而不是在收到第一张关于重复收费的支持工单之后才实现。

错误 7:事后才考虑身份验证

API 密钥适用于服务器到服务器的通信。OAuth 2.0 适用于代表用户操作的情况。JWT 是一种令牌格式,而不是身份验证方案——把它当作自动安全的做法会导致 none 算法漏洞。在首次外部消费者之前就做出身份验证决策,因为事后补救会很痛苦。

错误 8:将内部模型耦合到 API 响应

直接将数据库行序列化为 API 响应在重构之前是高效的。重命名列就会导致破坏性更改。添加像 password_hash 这样的内部字段会有意外泄露的风险。数据传输对象——明确的序列化器类,用于定义每个响应的结构——在内部实现和外部契约之间创建了明确的边界。

三个关键要点

  • 不能等的结构决策 包括版本控制、错误格式、认证模型以及内部模型与外部合同之间的边界。事后改造成本高。其他所有内容都可以迭代改进。
  • API 设计失误会外部化。 设计不佳的痛苦由消费者在你无法控制的时间线上承担。这种不对称性证明了相较于大多数内部工程决策,需要更多的前期关注。
  • 学习 Stripe、GitHub 和 Twilio。 不是因为它们有名,而是因为它们的设计选择是有意为之且有文档记录的。它们在一致性、分页、错误处理和版本控制方面使用的模式都有充分的理由。

阅读完整文章请访问 novvista.com,了解每个错误的详细拆解、真实实现示例以及 Stripe、GitHub 和 Twilio 如何树立标准的分析。

最初发布于 NovVista

0 浏览
Back to Blog

相关文章

阅读更多 »

代码整洁之道

Clean Code 的力量:解锁更好软件开发的秘密 作为开发者,你可能经常听到“clean code”这个词,但…

为什么学习 Node.js?

为什么要学习 Node.js?如果你正踏入开发世界或想要提升为程序员,学习 Node.js 可以成为最具战略性的决定之一……