
API开发中的日志记录价值
微服务架构是一种将单个应用程序拆分为多个小服务的软件架构风格,每个服务负责一个特定的业务功能,可以独立部署、扩展和维护。在微服务架构中,API 设计是关键组成部分,它决定了服务之间如何交互和协作,对系统的性能、可靠性和可维护性至关重要。本文将详细介绍微服务架构中的 API 设计原则、最佳实践和具体规范。
在微服务架构中,API 设计涉及以下几个核心概念:
RESTful API 是微服务架构中常用的 API 设计风格,它具有简洁、可读性强的特点。设计 RESTful API 时,应遵循以下原则:
/users
,特定用户可以通过 /users/{userId}
访问。随着 API 的不断演进,版本控制是必不可少的。推荐使用 URL 路径中的版本号,例如 /v1/users
。这样可以确保在发布新版本时不会影响现有客户端,同时也使得不同版本的 API 可以并存,方便过渡和测试。
在微服务环境中,安全性尤为重要。常见的身份认证方式包括:
统一的错误处理机制可以提高 API 的用户体验。应使用标准化的 HTTP 状态码来表示不同类型的错误,例如:
API 合约定义了服务提供者和消费者之间的明确协议,包括请求格式、响应格式、错误处理等。这有助于确保 API 的一致性和稳定性,同时也促进了团队内部和团队之间的有效沟通。
API 网关是微服务架构中的一个重要组件,它处于客户端和服务之间,提供了路由请求、认证、监控和缓存等功能。
在微服务架构中,独立地更新和部署服务是常见的需求。因此,对 API 进行有效的版本管理至关重要。
/v1/
、/v2/
)可以帮助客户端选择合适的 API 版本。在设计微服务中的 API 时,强化安全措施是不可或缺的环节,以确保数据的安全和隐私。
选择合适的数据传输格式对于 API 的性能和可用性有重大影响。
如无特别说明,路径、参数、变量等命名统一采用首字母小写的驼峰方式。
如无特别说明,字符编码统一采用 UTF-8。
为了简化沟通和理解,如非必要请勿使用 PUT、PATCH 和 DELETE,这三种请求方式均可使用 POST 结合路径中的操作来实现。
GET /user/list 列表查询
GET /user/info/1 ID 查询,如需查询多个,ID 列表通过 Query 参数传递,形如 ids=1,2,3
POST /user/create 创建
POST /user/update/1 更新,只更新传递的字段,未传递的字段保持不变
POST /user/replace/1 替换,整体更新,未传递的字段将清空
POST /user/delete/1 删除,如需删除多个,ID 列表通过请求体传递,形如 {"ids": [1, 2, 3]}
GET /user/list?gender=male&minAge=18
GET /user/infoByUsername?username=jack
GET /user/follow?followingId=1&followerId=2 涉及到多个 ID 组合才能定位资源时,统一通过 Query 参数传递
POST /user/sendVerifyCode
对于采用微服务架构的应用,需要通过路径前缀来区分前后端资源,以及不同的微服务。
/api
路径前缀下,可在反向代理层添加该前缀,在传递给后端服务时抹去该前缀,以便该前缀对后端服务来说无感知。/user
),该前缀同样对各微服务来说无感知。/user/create
(对外暴露的完整路径为 /api/user/user/create
,这里服务名和模块名同名)。对于内部使用的 API,自己可以控制客户端升级节奏,应避免使用 API 版本,因为维护多版本 API 的成本很高。对于对外开放的 API,由于无法控制使用方客户端升级节奏,那么可以通过多版本 API 来实现平滑升级,在废弃老版 API 之前给使用方留足够的升级时间。
API 版本号可在不同的层级上添加,以前面的创建用户 API /api/user/user/create
为例,按作用范围由大到小有以下几种方式:
/api/v1/user/user/create
在应用网关层级添加(推荐)。/api/user/v1/user/create
在微服务层级添加。/api/user/user/v1/create
在模块层级添加。/api/user/user/create/v1
在 API 层级添加。不建议为不同版本的服务启动不同的实例,随着版本的不断升级,后期的维护工作会越来越大。对于同一个服务的不同版本 API,应使用一套代码,新版 API Controller 可以通过继承老版 Controller 来尽量复用现有代码。
通过 HTTP 头来传递公共参数,优先使用 HTTP 标准头,没有合适的再自定义,自定义 HTTP 头需以 X- 打头。
HTTP 头 | 示例 | 用途 |
Authorization | Bearer | 认证服务颁发的 Token |
Accept-Language | zh-CN,zh;q=0.9,en-US,en;q=0.1 | 可接受的响应内容语言,优先使用权重高的 |
X-Client-Name | BasicAI | 客户端名称 |
X-Client-Version | v1.0.0 | 客户端版本 |
示例:
{
"username": "jack",
"password": "12345678",
"age": 17
}
HTTP 状态码设计的初衷是用于静态资源访问场景,对于 API 这种动态服务场景,许多状态码都不适用,或者根本无法表示各种千奇百怪的业务错误。因此这里推荐只使用下面这些少量的 HTTP 状态码,其它业务异常情况统一响应 200 状态码,并在响应体里通过 code 返回具体的业务错误码。
响应体为 JSON 对象,结构如下:
{
"code": "OK", // 业务错误码
"message": "", // 业务错误描述
"data": null // 业务数据
}
USER__USER__USERNAME_DUPLICATED
,其中前两级依次为服务和模块,一些与服务和模块无关的公共错误码没有前缀。data
字段返回,这样可以让后端省去大量的包装类定义,如果有多项那么只能再包一层,在 data
下通过不同字段区分,如果没有则为 null
。单项业务数据直接通过 data 字段返回示例:
{
"code": "OK",
"message": "",
"data": {
"id": 1,
"username": "jack"
}
}
多项业务数据需包一层示例:
{
"code": "OK",
"message": "",
"data": {
"user": {
"id": 1,
"username": "jack"
},
"roles": []
}
}
列表数据示例:
{
"code": "OK",
"message": "",
"data": {
"list": [],
"total": 1000
}
}
业务出错示例:
{
"code": "BILLING__PAY__MONEY_NOT_ENOUGH",
"message": "money not enough",
"data": null
}
适合客户端有翻页条,按页展示数据,数据集变化较慢的场景。
total
、pageNo
、pageSize
、list
来传递和返回总数(可选)、当前页码、每页条数和当页数据。{
"code": "ok",
"message": "",
"data": {
"total": 100,
"pageNo": 1,
"pageSize": 10,
"list": []
}
}
适合没有翻页条的流式加载模式场景,如果起始位置使用主键 ID、创建时间这样的排序字段,服务端可以通过大于或等于比较来加速查询,并且在数据集有变化时能够保证分批获取的数据不重复。
total
、offset
、limit
、list
来传递和返回总数(可选)、起始位置、返回条数和当页数据。{
"code": "ok",
"message": "",
"data": {
"total": 100,
"offset": 0,
"limit": 10,
"list": []
}
}
假设我们正在设计一个电商平台的微服务架构,其中包括用户服务、订单服务和支付服务。每个服务都有自己的 API,这些 API 通过 RESTful 设计原则进行设计,并实现了 OAuth 2.0 身份认证。我们为每个服务提供了详细的 Swagger 文档,并在持续集成过程中运行自动化测试,以确保各个服务间的交互顺畅。
POST /api/user/user/create
Content-Type: application/json
{
"username": "jack",
"password": "12345678",
"age": 17
}
GET /api/user/user/info/1
POST /api/order/order/create
Content-Type: application/json
{
"userId": 1,
"items": [
{
"itemId": 101,
"quantity": 2
},
{
"itemId": 102,
"quantity": 1
}
]
}
GET /api/order/order/list?userId=1
POST /api/payment/payment/create
Content-Type: application/json
{
"orderId": 1,
"amount": 100
}
GET /api/payment/payment/status/1
微服务架构下的 API 设计需要综合考虑资源管理、版本控制、安全性、错误处理以及文档和测试等多个方面。通过遵循这些最佳实践,我们可以构建出高效、可靠的 API,从而支持系统的可扩展性和灵活性。希望本文对您有所帮助,并为您的微服务架构设计提供了一些有价值的信息和见解。