📡 构建高可用通知系统:Kafka 在汇丰跨境支付中的实战应用
✅ 为什么写这篇?
汇丰的通知系统涉及支付、风控、合规等多个子系统,当一笔跨境转账成功后,消息需要可靠地被多个系统并发、无丢失、无重复地消费处理。
本篇将带你用 Kafka 构建一个高可用的“支付成功通知系统”,完整演示消息发布、消费者组处理、多副本保障等机制。
📌 场景还原
一笔汇款完成后,系统向 Kafka 推送成功消息:
- 风控系统消费后审计记录
- 账务系统消费后更新总账
- 客户通知系统消费后发送短信/邮件
🧰 技术栈与工具
| 技术 | 用途 |
|---|---|
| Kafka | 消息发布与订阅 |
| Node.js + kafkajs | 生产者 & 消费者客户端 |
| Docker | 快速搭建 Kafka 测试环境 |
📦 Kafka 快速启动(Docker)
# docker-compose.yml
version: '2'
services:
zookeeper:
image: wurstmeister/zookeeper
ports: [ "2181:2181" ]
kafka:
image: wurstmeister/kafka
ports: [ "9092:9092" ]
environment:
KAFKA_ADVERTISED_HOST_NAME: localhost
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
启动:
docker-compose up -d
🧪 实战代码:Node.js + KafkaJS
1️⃣ 安装依赖
npm install kafkajs
2️⃣ 生产者 producer.js
const { Kafka } = require('kafkajs');
const kafka = new Kafka({ clientId: 'hsbc-core', brokers: ['localhost:9092'] });
const producer = kafka.producer();
async function sendPaymentSuccess() {
await producer.connect();
const result = await producer.send({
topic: 'payment-success',
messages: [
{ key: 'order001', value: JSON.stringify({ orderId: '001', amount: 5000, currency: 'USD' }) }
],
});
console.log('✅ 已发送通知:', result);
await producer.disconnect();
}
sendPaymentSuccess();
3️⃣ 消费者(风控系统)consumer-audit.js
const { Kafka } = require('kafkajs');
const kafka = new Kafka({ clientId: 'audit-svc', brokers: ['localhost:9092'] });
const consumer = kafka.consumer({ groupId: 'audit-group' });
async function start() {
await consumer.connect();
await consumer.subscribe({ topic: 'payment-success', fromBeginning: true });
await consumer.run({
eachMessage: async ({ topic, partition, message }) => {
const payload = JSON.parse(message.value.toString());
console.log(`📘 审计服务接收:`, payload);
},
});
}
start();
4️⃣ 消费者(通知系统)consumer-notify.js
const kafka = new (require('kafkajs')).Kafka({ clientId: 'notify-svc', brokers: ['localhost:9092'] });
const consumer = kafka.consumer({ groupId: 'notify-group' });
consumer.connect().then(() => {
return consumer.subscribe({ topic: 'payment-success', fromBeginning: true });
}).then(() => {
return consumer.run({
eachMessage: async ({ message }) => {
const payload = JSON.parse(message.value.toString());
console.log(`📨 通知系统已发送短信给客户:订单 ${payload.orderId}`);
}
});
});
🖥️ 输出结果示意
# 启动 producer
✅ 已发送通知: [{ topicName: 'payment-success', partition: 0, errorCode: 0 }]
# consumer-audit.js 输出
📘 审计服务接收: { orderId: '001', amount: 5000, currency: 'USD' }
# consumer-notify.js 输出
📨 通知系统已发送短信给客户:订单 001
⚠️ 易错点总结
| 错误点 | 描述 |
|---|---|
| ❌ groupId 相同 | 多消费者抢同一份消息,只有一个会收到 |
| ❌ 消费 offset 未手动提交 | 重启后重复消费或错过消息 |
| ❌ partition 配置不当 | 所有消息都挤在一个消费者上,无法并行 |
✅ 推荐做法:
- 每个子系统用不同 groupId(保证各自都能收到)
- 多分区+多个消费者实现负载均衡
- 手动提交 offset 以提升稳定性(如需强一致性)
🎯 总结
- 本文用 Kafka + Node.js 构建了“支付通知系统”
- 实现了多系统并发消费、日志审计与客户提醒
- 结构可扩展性强,适用于银行类中间服务通信场景