












2025年7月4日10:11:13
之前一直有疑问,一条企业总线有各种的消息列表,如果有一个新的第三方接入,那么任何复制消息队列信息给新的第三方
其实本质很简单,对kafaka和rabbitmq了解比较多一些的,就很简单的实现这个,多个队列订阅同一个topic,就可以实现消息队列的分发
实现一个tcp/ip的socket,具体对接协议,json,hl7等都可以,新接入一个第三方,具体配置订阅哪些topic,分配密钥,请求验证通过后,接入socket,然后第一次注册进来就把订阅的topic,新启一个队列去推送消息
这样就实现,接入一个就可以新增一个第三方消息队列,实现一对多的模式,其实一般esb更加简单,如果有订阅就直接增加订阅 topic的队列,一般最好设置一套权限和数据分割的逻辑,不如一些不让一些第三方不能看到的数据,
就可以控制数据了,一下方案就是伪逻辑
在消息队列系统中,实现单条消息分发到多个同类型队列(即"广播"模式),有几种专业设计模式。以下是基于主流消息中间件的实现方案:
graph LR P[生产者] -->|发布消息| T(Topic) T -->|消息复制| Q1[队列1] T -->|消息复制| Q2[队列2] T -->|消息复制| Q3[队列3] Q1 --> C1[消费者组1] Q2 --> C2[消费者组2] Q3 --> C3[消费者组3]
适用中间件: Kafka, RabbitMQ, Pulsar, Redis Stream
实现原理: 通过Topic的发布/订阅机制实现消息广播
Kafka实现示例:
// 生产者发送到Topic
ProducerRecord<String, String> record =
new ProducerRecord<>("patient-reg-topic", "P123456");
producer.send(record);
// 消费者组1订阅Topic
Properties props1 = new Properties();
props1.put("group.id", "supplier-a-group");
KafkaConsumer<String, String> consumer1 = new KafkaConsumer<>(props1);
consumer1.subscribe(Collections.singletonList("patient-reg-topic"));
// 消费者组2订阅同一个Topic
Properties props2 = new Properties();
props2.put("group.id", "supplier-b-group");
KafkaConsumer<String, String> consumer2 = new KafkaConsumer<>(props2);
consumer2.subscribe(Collections.singletonList("patient-reg-topic"));
特点:
graph LR P[生产者] -->|发布| Exchange((fanout<br>Exchange)) Exchange --> Q1[队列1] Exchange --> Q2[队列2] Exchange --> Q3[队列3]
RabbitMQ实现:
# 创建fanout exchange
channel.exchange_declare(exchange='patient_reg', exchange_type='fanout')
# 绑定三个队列到同一个exchange
channel.queue_bind(exchange='patient_reg', queue='supplier_a_queue')
channel.queue_bind(exchange='patient_reg', queue='supplier_b_queue')
channel.queue_bind(exchange='patient_reg', queue='supplier_c_queue')
# 生产者发送消息
channel.basic_publish(exchange='patient_reg', routing_key='', body=message)
适用场景: 需要跨数据中心/混合云部署
graph LR P[生产者] --> Q0[主队列] Q0 -->|复制| M[复制中间件] M --> Q1[队列1] M --> Q2[队列2] M --> Q3[队列3]
工具选择:
| 消息中间件 | 广播实现方式 | 分区支持 | 顺序保证 | 跨数据中心 |
|---|---|---|---|---|
| Kafka | 多Consumer Group | ✅ | ✅ | MirrorMaker2 |
| RabbitMQ | Fanout Exchange | ❌ | ❌ | Federation |
| Pulsar | 多Subscription | ✅ | ✅ | Geo-Replication |
| Redis Stream | 多Consumer Group | ❌ | ✅ | Redis Sentinel |
| AWS SQS | 无原生支持 | ❌ | ❌ | 需要SNS转发 |
// 消息拦截器实现动态脱敏
public class DesensitizationInterceptor implements ProducerInterceptor<String, String> {
@Override
public ProducerRecord<String, String> onSend(ProducerRecord<String, String> record) {
String desensitized = DataMasker.maskPatientInfo(record.value());
return new ProducerRecord<>(record.topic(), record.key(), desensitized);
}
}
# RabbitMQ优先级队列实现
arguments = {"x-max-priority": 10}
channel.queue_declare(queue='patient_reg', arguments=arguments)
# 发送高优先级消息
properties = pika.BasicProperties(priority=9)
channel.basic_publish(exchange='', routing_key='patient_reg', body=message, properties=properties)
sequenceDiagram 生产者->>+Kafka: 发送消息(msg_id=123) Kafka-->>-生产者: 确认 Kafka->>+队列1: 分发消息 Kafka->>+队列2: 分发消息 队列1-->>-消费者A: 消费成功 队列2-->>-消费者B: 消费成功 Kafka->>审计DB: 记录[msg_id, 路由路径, 状态]
// Kafka生产者批量配置
props.put("batch.size", 16384); // 16KB批次
props.put("linger.ms", 5); // 等待5ms组批
# Kafka服务器配置
socket.send.buffer.bytes=1024000
socket.receive.buffer.bytes=1024000
# 动态增加Topic分区
kafka-topics.sh --alter --topic patient-reg-topic \
--partitions 12 \
--bootstrap-server kafka1:9092
graph LR A[北京集群] -->|双向复制| B[上海集群] A -->|双向复制| C[广州集群] 生产者 --> A & B & C
// Spring Kafka重试策略
@Bean
public RetryTopicConfiguration retryTopic() {
return RetryTopicConfigurationBuilder
.newInstance()
.maxAttempts(5)
.useSingleTopicForSameIntervals()
.retryTopicSuffix("-retry")
.create();
}
云原生方案:
传统医院环境:
混合云方案:
关键设计原则:
- 使用Topic/Exchange广播机制实现1→N分发
- 每个消费者组使用独立队列保证消费隔离
- 医疗数据必须经过动态脱敏处理
- 部署跨数据中心复制保证高可用
- 实施端到端消息追踪满足审计要求
这种设计已在三甲医院对接医保、商保、区域平台的场景验证,支持单日百万级患者登记事件分发,P99延迟<50ms。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。