六种用于可靠连接 Node.js 服务的集成模式
了解强大 Node.js 集成背后的核心模式:请求-响应、轮询、Webhook、API 密钥、JWT 与 OAuth 认证、带退避机制的重试,以及数据映射。
来源: 6 API Integration Patterns Every Node.js Integration Engineer Must Know
发送HTTP请求很简单;当其他系统响应缓慢、故障或结构不同之时仍保持集成正常运行才是真正的挑战。本指南介绍了Node.js服务与支付提供商、CRM系统、ERP系统以及彼此之间交互时常见的六种模式,同时还指出了那些会导致演示版本与可靠集成之间存在差距的隐患。
1. 请求-响应:同步处理的基准模式
在请求-响应模型中,客户端发送请求,服务器处理任务,然后通过同一连接返回结果。这种模式涵盖了大多数日常操作:登录、创建或更新记录、获取客户信息、删除资源等。
app.get("/users/:id", async (req, res) => {
const user = await db.findUser(req.params.id);
res.json(user);
});
这种方式的调试较为简单,也是CRUD操作的默认实现方式。其缺点在于处理耗时较长的任务:大型报告或大文件可能会超出客户端或代理的超时时间。还需注意,当用户不存在时,该处理程序会返回状态码200并附带null值;而真正的接口应当返回404状态码。
2. 轮询:持续查询直至任务完成
当无法立即生成结果时,服务器可以接收该任务,返回一个标识符,让客户端定期查询状态。典型应用场景包括等待付款处理完成、报告生成、视频转码或订单发货等。
启动任务后会返回该任务的ID:
POST /reports
Response:
{
"jobId": "abc123"
}
随后客户端会定期查询状态接口:
GET /reports/abc123/status
直到任务报告已完成为止:
{
"status": "completed"
}
轮询方式简单且易于通过防火墙,因此许多企业系统仍在使用它。但其缺点是会产生大量不必要的流量,因为大多数查询都会返回“尚未完成”。应合理间隔请求时间(如果设置了Retry-After则需遵守该时间),设定整体截止时间,并妥善处理请求“失败”和“完成”的情况。
3. Webhooks:让对方主动调用你
Webhooks改变了请求方向。不再由你的服务不断发起查询,而是在发生特定事件时——如支付成功、订单创建、消息到达、客户注册或库存变化——由服务提供商向你的端点发送HTTP请求。Stripe、Slack、GitHub和Shopify等都大量采用这种模式。
Express框架中的简易接收器示例:
app.post("/webhook/payment", (req, res) => {
const event = req.body;
if (event.type === "payment.success") {
console.log("Payment received!");
}
res.sendStatus(200);
});
这仅展示了基本结构,但实际生产环境中的接收器还需要更多功能:
- 验证发送方。任何人都可向公共URL发布内容。服务提供商通常会对每个数据包进行签名,因此在信任该事件之前必须检查该签名(通常需与原始请求体对比)。
- 预期会出现重复数据。由于系统会不断重试直到收到确认,因此同一事件可能会多次出现。应存储已处理事件的ID,并确保处理程序具有幂等性。
- 尽快确认接收。应迅速返回2xx状态码,将耗时的处理任务放入队列中;否则服务提供商可能会超时并重新发送数据。
由于能够消除轮询带来的流量,基于事件的集成方式越来越受到青睐。
4. 身份验证:确认调用者身份
每一次集成都始于凭证的传递。三种方法即可覆盖大多数场景。
API密钥
最简单的方案是通过请求头传递共享密钥:
GET /users
x-api-key: abc123xyz
在使用 axios 的 Node.js 应用中,密钥应来自配置文件,而非源代码:
axios.get(url, {
headers: {
"x-api-key": process.env.API_KEY
}
});
API 密钥适用于内部工具以及简单的服务器间集成。它们本身不包含有效期或用户身份信息,因此应按照提供商允许的范围定期更换并限制其使用范围。
JSON Web Tokens
JWT 可实现无状态认证。常见流程如下:
- 用户登录。
- 服务器生成带签名的令牌。
- 客户端保存该令牌。
- 后续的每个请求都在请求头中携带该令牌:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
在 Node.js 中生成令牌的步骤:
const token = jwt.sign(
{ userId: 1 },
process.env.JWT_SECRET
);
任何拥有验证密钥的服务都无需会话存储即可验证令牌,这非常适合微服务架构。但问题在于令牌的撤销:令牌在过期前始终有效,因此必须设置expiresIn字段,而此代码片段并未包含该设置。
OAuth 2.0
OAuth 2.0是实现委托访问功能的基础:比如“使用Google登录”、Facebook登录、Microsoft企业单点登录、CRM连接器以及任何代表用户操作的第三方应用。在常见的授权码流程中:
- 用户在服务提供商处批准所请求的访问权限。
- 服务提供商会重定向并返回一个短期有效的授权码。
- 您的服务器用该授权码换取访问令牌。
- 随后使用该访问令牌发起API调用。
值得深入学习的包括:访问令牌和刷新令牌、授权码流程、用于机器对机器调用的客户端凭证流程、PKCE以及建立在OAuth之上的身份层OpenID Connect。
5. 韧性:为故障设计
网络会超时,依赖项也会失效。可靠的集成系统必须考虑到这种情况。
重试失败的调用
一个基本的重试循环:
for (let i = 0; i < 3; i++) {
try {
return await axios.get(url);
} catch (error) {
console.log("Retrying...");
}
}
按照当前的实现,它会立即进行重试而不会暂停;如果三次尝试都失败,它会返回undefined而非抛出最后的错误,因此调用方无法知道出了什么问题。应在最后一次尝试后重新抛出异常,并且仅对暂时性故障(网络错误、超时、5xx错误、429错误)进行重试,而对于每次都会导致同样失败的4xx错误则不应重试。除非API支持幂等性键,否则请谨慎对支付等非幂等性请求进行重试。
超时设置
如果没有设置超时,请求可能会无限期挂起并占用资源。务必设置超时时间:
axios.get(url, {
timeout: 5000
});
指数退避策略
以固定间隔重试只会不断冲击出现故障的服务:
1s
1s
1s
1s
每次将等待时间翻倍,可以给服务恢复留出空间:
1s
2s
4s
8s
16s
该计算只需一行代码即可完成:
const delay = attempt =>
Math.pow(2, attempt) * 1000;
需限制最大延迟时间,并加入随机抖动,以避免大量客户端同时失败时同步重试。
断路器机制
断路器会统计对下游服务的失败次数,一旦超过阈值,就会在冷却期停止调用该服务,之后再尝试发送请求。这有助于防止级联故障、资源耗尽以及整个系统的瘫痪。在Node.js中,Opossum是常见的断路器实现;Java中使用Resilience4j来实现类似功能,而较旧的系统中则使用Hystrix。
6. 数据转换:系统间的互转
两个系统在数据格式上很少一致,因此集成工作的很大一部分就是进行数据转换。
字段映射
某个系统使用驼峰命名法:
{
"firstName": "John"
}
而另一个系统则要求使用下划线命名法:
{
"first_name": "John"
}
一个小型映射工具可实现二者之间的转换:
function transform(user) {
return {
first_name: user.firstName
};
}
纯函数形式的映射器易于进行单元测试,同时还能将提供方的特殊格式问题与业务逻辑分离。
JSON与XML
许多传统系统仍使用XML格式,而较新的服务则生成JSON格式,因此集成层通常需要在这两种格式之间进行双向转换。
日期
一方可能会发送ISO格式的日期:
2026-06-26
而另一方则要求使用日优先的格式:
26/06/2026
应明确进行转换,并在日期值包含时间信息时注明时区;跨越午夜的日期处理错误是集成中常见的故障。
货币金额
有一种服务要求使用小数形式表示金额:
{
"amount": 10.50
}
另一种服务则要求使用整数形式的较小单位:
{
"amount_cents": 1050
}
浮点数无法精确表示所有小数,因此在转换时需要进行四舍五入(例如 Math.round(amount * 100)),内部处理时应优先使用整数形式的分。
这些模式在实践中的结合方式
典型的企业架构会在多个后端服务之前设置一个 Node.js 网关:
Frontend
|
Node.js API Gateway
|
+-- Authentication Service
+-- Payment Service
+-- CRM Service
+-- ERP Systems
+-- Notification Service
这些连接整合了上述各种模式:请求-响应 API、JWT 和 OAuth、Webhook、重试与断路器机制、数据转换层,以及监控和日志功能。对于开始从事集成工作的工程师而言,最先能带来成效的领域包括 REST API、Webhook、JWT、OAuth 2.0、数据转换和事件驱动设计,随后是重试与容错技术,最后才是轮询和断路器机制。
核心要点
- 对于快速操作,使用请求-响应模式;当处理时间较长时,则改用轮询或Webhook方式。
- 验证Webhook签名,去重事件并迅速确认接收。
- 将凭证存储在配置文件中,为令牌设置有效期,并彻底掌握OAuth流程。
- 仅对短暂性故障进行重试,同时设置超时时间、限制指数退避次数及抖动幅度。
- 将数据映射逻辑封装在经过测试的纯函数中,尤其要谨慎处理日期和金额相关数据。