Spring Boot 整合分布式消息平台 Pulsar

整合Spring Boot和Pulsar实现可扩展的消息处理 在实际项目中,可以根据需求进一步优化和扩展Pulsar的使用,例如配置不同的主题和分区、实现更复杂的消息处理逻辑等。Apache Pulsar作为一个分布式消息流平台,具备高吞吐、低延迟、多租户支持等优势,是很多高性能消息处理场景的理想选择。Pulsar的架构包括Brokers、Bookies(Apache BookKeeper的存储节点)和ZooKeeper协调服务,提供了高可用性和高性能的消息传递和存储服务。最后,我们编写一个简单的测试类来验证生产者和消费者的工作。 阅读详情

点击上方“芋道源码”,选择“设为星标”

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

 

来源:君哥聊技术


作为优秀的消息流平台,Pulsar 的使用越来越多,这篇文章讲解 Pulsar 的 Java 客户端。

部署 Pulsar

Pulsar 的部署方式主要有 3 种,本地安装二进制文件、docker 部署、在 Kubernetes 上部署。

本文采用 docker 部署一个单节点的 Pulsar 集群。实验环境是 2 核 CPU 和 4G 内存。

部署命令如下:

docker run -it -p 6650:6650  -p 8080:8080 --mount source=pulsardata,target=/pulsar/data --mount source=pulsarconf,target=/pulsar/conf apachepulsar/pulsar:2.9.1 bin/pulsar standalone

安装过程可能会出现下面的错误:

unknown flag: --mount
See 'docker run --help'.

这是因为 docker 版本低,不支持 mount 参数,把 docker 版本升级到 17.06 以上就可以了。

部署过程中可能会因为网络的原因失败,多试几次就可以成功了。如果看到下面的日志,就说明启动成功了。

2022-01-08T22:27:58,726+0000 [main] INFO  org.apache.pulsar.broker.PulsarService - messaging service is ready, bootstrap service port = 8080, broker url= pulsar://localhost:6650, cluster=standalone

本地单节点集群启动后,会创建一个 namespace,名字叫 public/default

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

Pulsar 客户端

目前 Pulsar 支持多种语言的客户端,包括:

Java 客户端

Go 客户端

Python 客户端

C++ 客户端

Node.js 客户端

WebSocket 客户端

C# 客户端

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

SpringBoot 配置

使用 SpringBoot 整合 Pulsar 客户端,首先引入 Pulsar 客户端依赖,代码如下:

<dependency>
    <groupId>org.apache.pulsar</groupId>
    <artifactId>pulsar-client</artifactId>
    <version>2.9.1</version>
</dependency>

然后在 properties 文件中添加配置:

# Pulsar 地址
pulsar.url=pulsar://192.168.59.155:6650
# topic
pulsar.topic=testTopic
# consumer group
pulsar.subscription=topicGroup

创建 Client

创建客户端非常简单,代码如下:

client = PulsarClient.builder()
                .serviceUrl(url)
                .build();

上面的 url 就是 properties 文件中定义的 pulsar.url 。

创建 Client 时,即使集群没有启成功,程序也不会报错,因为这时还没有真正地去连接集群。

创建 Producer

producer = client.newProducer()
                .topic(topic)
                .compressionType(CompressionType.LZ4)
                .sendTimeout(0, TimeUnit.SECONDS)
                .enableBatching(true)
                .batchingMaxPublishDelay(10, TimeUnit.MILLISECONDS)
                .batchingMaxMessages(1000)
                .maxPendingMessages(1000)
                .blockIfQueueFull(true)
                .roundRobinRouterBatchingPartitionSwitchFrequency(10)
                .batcherBuilder(BatcherBuilder.DEFAULT)
                .create();

创建 Producer,会真正的连接集群,这时如果集群有问题,就会报连接错误。

下面解释一下创建 Producer 的参数:

topic :Producer 要写入的 topic。

compressionType :压缩策略,目前支持 4 种策略 (NONE、LZ4、ZLIB、ZSTD),从 Pulsar2.3 开始,只有 Consumer 的版本在 2.3 以上,这个策略才会生效。

sendTimeout :超时时间,如果 Producer 在超时时间为收到 ACK,会进行重新发送。

enableBatching :是否开启消息批量处理,这里默认 true,这个参数只有在异步发送 (sendAsync) 时才能生效,选择同步发送会失效。

batchingMaxPublishDelay :批量发送消息的时间段,这里定义的是 10ms,需要注意的是,设置了批量时间,就不会受消息数量的影响。批量发送会把要发送的批量消息放在一个网络包里发送出去,减少网络 IO 次数,大大提高网卡的发送效率。

batchingMaxMessages :批量发送消息的最大数量。

maxPendingMessages :等待从 broker 接收 ACK 的消息队列最大长度。如果这个队列满了,producer 所有的 sendAsync 和 send 都会失败,除非设置了 blockIfQueueFull 值是 true。

blockIfQueueFull :Producer 发送消息时会把消息先放入本地 Queue 缓存,如果缓存满了,就会阻塞消息发送。

roundRobinRouterBatchingPartition-SwitchFrequency :如果发送消息时没有指定 key,那默认采用 round robin 的方式发送消息,使用 round robin 的方式,切换 partition 的周期是 (frequency * batchingMaxPublishDelay)。

创建 Consumer

Pulsar 的消费模型如下图:

cdf7acbce8a99846038e537bf05dd17e.png
图片

从图中可以看到,Consumer 要绑定一个 subscription 才能进行消费。

consumer = client.newConsumer()
        .topic(topic)
        .subscriptionName(subscription)
        .subscriptionType(SubscriptionType.Shared)
        .subscriptionInitialPosition(SubscriptionInitialPosition.Earliest)
        .negativeAckRedeliveryDelay(60, TimeUnit.SECONDS)
        .receiverQueueSize(1000)
        .subscribe();

下面解释一下创建 Consumer 的参数:

topic :Consumer 要订阅的 topic。

subscriptionNam e:consumer 要关联的 subscription 名字。

subscriptionType :订阅类型,Pulsar 支持四种类型订阅:

  • Exclusive :独占模式,同一个 Topic 只能有一个消费者,如果多个消费者,就会出错。

  • Failover :灾备模式,同一个 Topic 可以有多个消费者,但是只能有一个消费者消费,其他消费者作为故障转移备用,如果当前消费者出了故障,就从备用消费者中选择一个进行消费。如下图:

  • 0d76cec0d40eb1072b0699e98a118e6c.png

    图片
  • Shared :共享模式,同一个 Topic 可以由多个消费者订阅和消费。消息通过 round robin 轮询机制分发给不同的消费者,并且每个消息仅会被分发给一个消费者。当消费者断开,如果发送给它消息没有被消费,这些消息会被重新分发给其它存活的消费者。如下图:a5dd25a33cdf115729360ca73f7da3b5.png

  • Key_Shared :消息和消费者都会绑定一个key,消息只会发送给绑定同一个key的消费者。如果有新消费者建立连接或者有消费者断开连接,就需要更新一些消息的 key。跟 Shared 模式相比,Key_Shared 的好处是既可以让消费者并发地消费消息,又能保证同一Key下的消息顺序。如下图:8ea882677bb714aadf6bf6c4c93c0fcd.png

subscriptionInitialPosition :创建新的 subscription 时从哪里开始消费,有两个选项:

  • Latest :从最新的消息开始消费

  • Earliest :从最早的消息开始消费

negativeAckRedeliveryDelay :消费失败后间隔多久 broker 重新发送。

receiverQueueSize :在调用 receive 方法之前,最多能累积多少条消息。可以设置为 0,这样每次只从 broker 拉取一条消息。在 Shared 模式下,receiverQueueSize 设置为 0,可以防止批量消息多发给一个 Consumer 而导致其他 Consumer 空闲。

Consumer 接收消息有四种方式:同步单条、同步批量、异步单条和异步批量,代码如下:

Message message = consumer.receive()
CompletableFuture<Message> message = consumer.receiveAsync();
Messages message = consumer.batchReceive();
CompletableFuture<Messages> message = consumer.batchReceiveAsync();

对于批量接收,也可以设置批量接收的策略,代码如下:

consumer = client.newConsumer()
    .topic(topic)
    .subscriptionName(subscription)
        .batchReceivePolicy(BatchReceivePolicy.builder()
        .maxNumMessages(100)
        .maxNumBytes(1024 * 1024)
        .timeout(200, TimeUnit.MILLISECONDS)
        .build())
    .subscribe();

代码中的参数说明如下:

maxNumMessages :批量接收的最大消息数量。

maxNumBytes :批量接收消息的大小,这里是 1MB。

测试

首先编写 Producer 发送消息的代码,如下:

public void sendMsg(String key, String data) {
    CompletableFuture<MessageId> future = producer.newMessage()
        .key(key)
        .value(data.getBytes()).sendAsync();
    future.handle((v, ex) -> {
        if (ex == null) {
            logger.info("发送消息成功, key:{}, msg: {}", key, data);
        } else {
            logger.error("发送消息失败, key:{}, msg: {}", key, data);
        }
        return null;
    });
    future.join();
    logger.info("发送消息完成, key:{}, msg: {}", key, data);
}

然后编写一个 Consumer 消费消息的代码,如下:

public void start() throws Exception{
    while (true) {
        Message message = consumer.receive();
        String key = message.getKey();
        String data = new String(message.getData());
        String topic = message.getTopicName();
        if (StringUtils.isNotEmpty(data)) {
            try{
                logger.info("收到消息, topic:{}, key:{}, data:{}", topic, key, data);
            }catch(Exception e){
                logger.error("接收消息异常,topic:{}, key:{}, data:{}", topic, key, data, e);
            }
        }
        consumer.acknowledge(message);
    }
}

最后编写一个 Controller 类,调用 Producer 发送消息,代码如下:

@RequestMapping("/send")
@ResponseBody
public String send(@RequestParam String key, @RequestParam String data) {
    logger.info("收到消息发送请求, key:{}, value:{}", key, data);
    pulsarProducer.sendMsg(key, data);
    return "success";
}

调用 Producer 发送一条消息,key=key1,data=data1,具体操作为在浏览器中输入下面的 url 后回车:

http://192.168.157.1:8083/pulsar/send?key=key1&data=data1

可以看到控制台输出下面日志:

2022-01-08 22:42:33,199 [pulsar-client-io-6-1] [INFO] boot.pulsar.PulsarProducer - 发送消息成功, key:key1, msg: data1
2022-01-08 22:42:33,200 [http-nio-8083-exec-1] [INFO] boot.pulsar.PulsarProducer - 发送消息完成, key:key1, msg: data1
2022-01-08 22:42:33,232 [Thread-22] [INFO] boot.pulsar.PulsarConsumer - 收到消息, topic:persistent://public/default/testTopic, key:key1, data:data1
2022-01-08 22:43:14,498 [pulsar-timer-5-1] [INFO] org.apache.pulsar.client.impl.ConsumerStatsRecorderImpl - [testTopic] [topicGroup] [7def6] Prefetched messages: 0 --- Consume throughput received: 0.02 msgs/s --- 0.00 Mbit/s --- Ack sent rate: 0.02 ack/s --- Failed messages: 0 --- batch messages: 0 ---Failed acks: 0
2022-01-08 22:43:14,961 [pulsar-timer-9-1] [INFO] org.apache.pulsar.client.impl.ProducerStatsRecorderImpl - [testTopic] [standalone-9-0] Pending messages: 0 --- Publish throughput: 0.02 msg/s --- 0.00 Mbit/s --- Latency: med: 69.000 ms - 95pct: 69.000 ms - 99pct: 69.000 ms - 99.9pct: 69.000 ms - max: 69.000 ms --- Ack received rate: 0.02 ack/s --- Failed messages: 0

从日志中看到,这里使用的 namespace 就是创建集群时生成的public/default。

总结

从 SpringBoot 整合 Java 客户端使用来看,Pulsar 的 api 是非常友好的,使用起来方便简洁。Consumer 的使用需要考虑多一些,需要考虑到批量、异步以及订阅类型。



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢:

15f1c3a5261cdd646f763b07eb03745c.png

已在知识星球更新源码解析如下:

8157f86da5021e718e5f61a879511829.jpeg

b7052f2d0de214a58296bd860dfae797.jpeg

96ce632b48ffd653415ff17985454b21.jpeg

f9b603c8483282b2f1155791b867e14d.jpeg

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
VSCode连接SAP ABAP开发环境 本文介绍了使用VSCode连接ABAP开发环境的详细步骤。首先通过SICF或SMICM事务码获取ABAP连接地址,然后安装ABAP remote filesystem插件。提供了两种创建连接的方法:通过命令面板逐步配置(输入服务器地址、账号、系统标识等)或直接编辑JSON配置文件。最后通过命令面板选择已创建的连接即可完成连接,连接成功后可在VSCode左侧工作区查看ABAP系统内容进行开发。JSON配置方式更为简便推荐。整个流程帮助开发者摆脱复杂的Eclipse配置,实现快速便捷的ABAP开发环境搭建。 阅读详情

相关推荐

智能座舱音频系统集成与调试:从芯片选型到音质优化实战

在智能座舱域控制器架构中,音频系统已从简单的功放加扬声器演进为SoC、数字音频总线、外部DSP与多通道功放协同的复杂子系统。TDM总线的时隙分配、PDM麦克风阵列的信号完整性,以及AEC回声消除算法如何与硬件协同,直接决定多音区体验和语音交互的可靠性。工程实践中,音频调试的关键在于先理顺供电、接地、时钟与数据路由,再针对功放削波、采样率失配、TDM slot错位等典型问题进行系统性排查。从芯片选型到系统级指标验收,只有将音频链路视为整车电子电气架构的一个协同整体,才能真正实现从“响”到“好听”的跨越。本文结

weixin_30162121的博客 372

SpringBoot整合分布式消息平台Pulsar

作为优秀的消息流平台,Pulsar 的使用越来越多,这篇文章讲解 Pulsar 的 Java 客户端。 部署 Pulsar Pulsar 的部署方式主要有 3 种,本地安装二进制文件、docker 部署、在 Kubernetes 上部署。 本文采用 docker 部署一个单节点的 Pulsar 集群。实验环境是 2 核 CPU 和 4G 内存。 部署命令如下: dockerrun-it-p6650:6650-p8080:8080--mountsource=pulsardata,...

20年码农 1606

python画弗里德曼(Friedman) 检验和秩和检验(Nemenyi)检验图

python画弗里德曼(Friedman) 检验和秩和检验(Nemenyi)检验图 画好后效果图 实现代码如下 import matplotlib.pyplot as plt #算法平均排名 _alg_=[1.405,2.643,2.786,2.167] y=[1,2,3,4]#alg1,alg2,alg3,alg4 通过Nemenyi测试计算得到的临界值CD CD=1.024 h_CD=CD/2 plt.figure(figsize=(10,6)) plt.scatter(_alg_,y,s=10

大模型天花板 4465

Spring Boot项目集成Pulsar

由Yahoo开发,并随后作为Apache软件基金会的一部分开源,Pulsar拥有独特的架构,将消息存储和消息处理分开,实现了出色的可扩展性和可靠性。随着物联网设备生成海量数据的增加,Pulsar为物联网应用提供了一个理想的平台,用于实时接收、处理和分析物联网数据流。凭借其可扩展的架构、可靠的消息传递和灵活的特性,Pulsar使组织能够构建强大的实时数据处理管道,推动创新和价值创造。作为Apache软件基金会的一部分,Pulsar受益于充满活力的社区和丰富的集成和扩展生态系统。5、pulsar公用方法。

Demon_Hao的博客 2633

散户逆袭神器:用通达信DIY指数发现下一个光伏储能(附龙头股筛选模板)

本文详细介绍了如何利用通达信软件的自定义指数功能,构建个人专属的行业监控工具,以发现类似光伏储能这样的潜力赛道。文章提供了从零开始的指数编制步骤、核心的龙头股筛选模板,以及五个关键的数据校验技巧,帮助散户投资者实现机构级的行业分析与机会挖掘,有效提升投资决策能力。

w3x4y的博客 485

机器学习---xgboost算法

问题上表现的十分顶尖,本节将较详细的介绍XGBoost的算法原理。成和剪枝分别对应了经验风险最小化和结构风险最小化, XGBoost的决策树生成是结构风险最小。式(1.1)称为经验风险最小化,训练得到的模型复杂度较高。出结果, 是模型的输出结果;等式右边第⼀部分是模型的训练误差,第⼆部分是正则化项,这里。其中,F是假设空间,假设空间是在已知属性和属性可能取值的情况下,对所有可能满足目标的情。最小化,结构风险最小化的模型往往对训练数据以及未知的测试数据都有较好的预测。的正则化项是K棵树的正则化项相加而来的。

weixin_43961909的博客 1万+

Spring Boot整合Apache Pulsar:从消息队列到云原生消息流的架构升级实践

消息队列作为分布式系统解耦、异步通信的核心组件,其设计原理经历了从传统代理模式到现代云原生架构的演进。传统方案如RabbitMQ基于AMQP协议,通过Exchange、Queue和Binding实现路由,但在高吞吐、低延迟和弹性扩展场景下面临挑战。Apache Pulsar作为新一代云原生消息流平台,其价值在于采用计算与存储分离的分层架构,支持多租户、统一的消息和流处理模型,提供了更强的弹性与一致性保障。在微服务架构中,消息中间件的选型直接影响着系统的可靠性、可观测性和运维成本。本文聚焦于如何将Pulsar

weixin_30443075的博客 422

智能办公助手——OpenClaw办公自动化集成(2026办公版)

OpenClaw智能办公助手是一款集成任务管理、文档处理等功能的办公自动化系统。该系统采用Python实现,核心功能包括:1)任务管理系统,支持任务增删改查、状态跟踪和统计报表生成;2)文档智能助手,提供文档处理能力。任务管理模块具备优先级设置、状态变更、时间记录等功能,并能生成包含完成率等指标的任务报告。该系统旨在通过自动化办公流程提升工作效率,减少重复性工作。开发者可利用这些模块构建完整的智能办公解决方案。

一键难忘的博客 350

Spring Boot整合Apache Pulsar实战:从设计到调优的完整指南

在分布式系统架构中,消息队列是实现服务解耦、异步通信和流量削峰的核心组件。其原理在于通过生产者-消费者模型,将消息暂存于中间件,实现应用间的可靠数据传递。这一技术价值在于构建高可用、可扩展的事件驱动架构,广泛应用于订单处理、日志收集和实时通知等场景。随着云原生和微服务的发展,对消息平台的扩展性、多租户和成本控制提出了更高要求。Apache Pulsar凭借其计算存储分离的架构和统一的消息模型,成为应对这些挑战的优选方案。本文聚焦于如何将Pulsar与Spring Boot这一主流Java框架深度整合,通过封

weixin_33708432的博客 432

python中视觉检测怎么将多个面拍照的图片合成一个3d图像,用什么技术或者什么模型?

🏆本文收录于 《全栈Bug调优(实战版)》 专栏,该专栏专注于分享我在真实项目开发中遇到的各类疑难Bug及其深层成因,并系统提供高效、可复现的解决思路和实操方案。无论你是刚入行的新手开发者,还是拥有多年项目经验的资深工程师,本专栏都将为你提供一条系统化、高质量的问题排查与优化路径,助力你加速成长,攻克技术壁垒,迈向技术价值最大化与职业发展的更高峰🚀!

**My Coding Family** 710

机器学习之多种算法优缺点总结及优化方法

一、无监督算法: 1、聚类算法:Kmeans 2、关联规则算法:Apriori 二、有监督算法 1、分类算法 决策树(Decision Tree) 支持向量机(SVM) K近邻(kNN,k-NearestNeighbor) 朴素贝叶斯 逻辑回归 2、回归算法 线性回归 多项式回归 3、集成算法 a、bagging(Bootstrapped Aggregation) 随机森林 ...

平原的博客 7081
上一篇: 23 届校招技术岗薪资汇总
下一篇: 老板:给我按 DDD 设计这个新项目~
公众号-芋道源码
博客等级 码龄10年 1634粉丝 377原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值