前言
Apache Pulsar 作为新一代云原生消息队列,凭借其多租户、持久化、高可用等特性,正在被越来越多的企业采用。然而,原生的 Pulsar Java 客户端集成到 Spring Boot 项目时,往往需要大量样板代码------连接管理、序列化、重试逻辑、健康检查......每个团队都在重复"造轮子"。
今天给大家介绍一个开源项目:seven-spring-mq-pulsar-starter ,它的目标只有一个:让 Spring Boot 接入 Pulsar,像用 Spring Data 一样简单。
GitHub:github.com/qwzhang01/s... Maven:
io.github.qwzhang01:seven-spring-mq-pulsar-starter
一、为什么需要这个 Starter?
先来看看直接使用 Pulsar 原生客户端的痛点:
| 场景 | 原生 Pulsar 客户端 | 本 Starter |
|---|---|---|
| 初始化连接 | 手动 new PulsarClient,管理生命周期 | 自动装配,零代码 |
| 消费者注册 | 手动创建 Consumer,写轮询循环 | @PulsarListener 一个注解搞定 |
| 多租户切换 | 每个消费者手动提取 metadata、切换上下文 | 拦截器自动传播 |
| 消息路由 | 在业务代码里写 if/switch 判断消息类型 | msgRoute 声明式路由 |
| 失败重试 | 自己实现退避算法 | 配置即用,支持指数退避 |
| 死信队列 | 手动实现 DLQ topic 和转发逻辑 | 自动处理,可自定义 Handler |
二、核心功能一览
🚀 一键启用
只需在启动类加一个注解:
java
@SpringBootApplication
@EnablePulsar
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
然后在 application.yml 里配置连接地址:
yaml
spring:
pulsar:
enabled: true
service-url: pulsar://localhost:6650
admin-url: http://localhost:8080
完成。开始写业务代码。
📨 消息发送:同步、异步、延迟,随你选
java
@Service
public class OrderService {
@Autowired
private PulsarMessageSender messageSender;
// 同步发送
public void sendOrder(Order order) {
messageSender.send("order-events", order);
}
// 异步发送,不阻塞主线程
public void sendOrderAsync(Order order) {
messageSender.sendAsync("order-events", order)
.thenAccept(id -> log.info("发送成功: {}", id));
}
// 延迟消息,30秒后投递
public void sendDelayed(Order order) {
messageSender.sendDelayed("order-events", order, 30_000);
}
}
👂 消息监听:注解声明,极致简洁
java
@Component
public class OrderEventListener {
@PulsarListener(topic = "order-events", subscription = "order-processor")
public void handleOrderEvent(Order order) {
orderService.process(order);
}
// 共享订阅,多实例并行消费
@PulsarListener(
topic = "payment-requests",
subscription = "payment-processor",
subscriptionType = "Shared"
)
public void processPayment(PaymentRequest request) {
paymentGateway.process(request);
}
}
🛣️ 亮点功能:消息路由(msgRoute)
这是本 Starter 最有特色的功能之一。
在传统做法里,同一个 topic 下有不同业务类型的消息,消费者需要:
- 拿到消息
- 判断消息类型
- 手动 dispatch 到不同处理逻辑
样板代码多,且容易出 Bug。
本 Starter 的方案:发送时在元数据里打标,消费时根据标记自动路由到对应的方法。
发送端:
java
MsgContext.setMsgRoute("order.created");
pulsarTemplate.send("order-events", event);
MsgContext.remove();
消费端:声明式绑定,一个方法只处理一种业务类型
java
@PulsarListener(topic = "order-events", subscription = "order-processor", msgRoute = "order.created")
public void handleOrderCreated(OrderEvent event) {
orderService.processNewOrder(event);
}
@PulsarListener(topic = "order-events", subscription = "order-processor", msgRoute = "order.cancelled")
public void handleOrderCancelled(OrderEvent event) {
orderService.processCancelledOrder(event);
}
也支持一个监听器处理多种路由(multiRoute = true):
java
@PulsarListener(topic = "business-events", subscription = "multi-route-processor", multiRoute = true)
public void handleMultiRoute(Message<BusinessEvent> message) {
String msgRoute = message.getProperties().get(MsgMetaKey.MSG_ROUTE.getCode());
switch (msgRoute) {
case "user.registration": handleUserRegistration(message.getValue()); break;
case "order.payment": handleOrderPayment(message.getValue()); break;
case "inventory.update": handleInventoryUpdate(message.getValue()); break;
}
}
🔐 多租户支持:拦截器自动传播上下文
SaaS 系统的核心挑战之一是多租户隔离。本 Starter 通过 MetaMessageInterceptor 抽象,让租户上下文在消息收发过程中自动流转:
java
@Component
public class TenantContextInterceptor extends MetaMessageInterceptor {
@Override
public void buildSendContext() {
// 发送时自动注入当前租户 ID 到消息元数据
MsgContext.setCorpKey(TenantContext.getCurrentTenant());
}
@Override
public boolean buildReceiveContext(String corpKey) {
// 消费时根据元数据自动切换租户
return tenantService.switchTenant(corpKey);
}
@Override
public int getOrder() { return 1; }
}
不需要在每个 @PulsarListener 里手动提取和设置租户,彻底消除重复代码。
🔄 重试 + 💀 死信队列:开箱即用
yaml
spring:
pulsar:
retry:
enabled: true
max-retries: 3
initial-delay: 1s
multiplier: 2.0 # 指数退避
max-delay: 30s
dead-letter:
enabled: true
max-retries: 5
retry:
smart-strategy-enabled: true
jitter-enabled: true # 加随机抖动,避免惊群效应
死信消息还可以自定义处理逻辑,比如落库、告警:
java
@Component
public class CustomDeadLetterHandler implements DeadLetterQueueHandler {
@Override
public void handleDeadLetter(String originalTopic, Message<?> message, Exception exception) {
// 存入数据库、发送告警通知......
deadLetterRepository.save(buildRecord(originalTopic, message, exception));
alertService.notify("消息处理失败:" + originalTopic);
}
}
🎯 事务消息:@PulsarTransactional 一行搞定
java
@Service
public class MessageService {
@PulsarTransactional
public void sendMessages(String topic, List<String> messages) {
Transaction transaction = PulsarTransactionUtils.getCurrentTransaction();
for (String message : messages) {
pulsarTemplate.send(topic, message, transaction);
}
// 正常返回自动提交,异常自动回滚
}
}
💊 健康检查:与 Spring Actuator 无缝集成
java
@GetMapping("/health/pulsar")
public ResponseEntity<?> checkPulsarHealth() {
Map<String, Object> health = pulsarHealthIndicator.health();
return "UP".equals(health.get("status"))
? ResponseEntity.ok(health)
: ResponseEntity.status(503).body(health);
}
三、快速上手
1. 引入依赖(Maven)
xml
<dependency>
<groupId>io.github.qwzhang01</groupId>
<artifactId>seven-spring-mq-pulsar-starter</artifactId>
<version>${pulsar-spring.version}</version>
</dependency>
2. 环境要求
- Java 17+
- Spring Boot 3.0+
- Apache Pulsar 3.2.4+
3. 最小配置
yaml
spring:
pulsar:
enabled: true
service-url: pulsar://localhost:6650
admin-url: http://localhost:8080
4. 就这些了 ,开始写你的 @PulsarListener。
四、适合哪些场景?
- 电商系统:订单、支付、库存等多业务类型消息的统一路由处理
- SaaS 平台:多租户架构下的消息上下文自动隔离传播
- 微服务通信:各微服务通过 Pulsar 解耦,事件驱动架构
- 高并发系统:批量异步发送 + Shared 订阅并行消费,提升吞吐
五、总结
seven-spring-mq-pulsar-starter 的核心理念是:把 Pulsar 集成的复杂性封装起来,把业务开发的简单性还给开发者。
它不是对 Pulsar 的简单封装,而是在 Spring Boot 生态范式下(注解驱动、配置即用、自动装配)重新思考了 Pulsar 集成的最佳实践,特别是 msgRoute 消息路由和 MetaMessageInterceptor 多租户拦截器这两个特性,在实际业务场景中能显著减少样板代码和降低出错概率。
项目目前在积极维护中,欢迎 Star、提 Issue 或贡献 PR。
项目地址 :github.com/qwzhang01/s...
如果这个项目对你有帮助,别忘了点个 ⭐ 支持一下!