参考教程
https://pulsar.apache.org/docs/2.10.x/client-libraries-java/
https://cloud.tencent.com/document/product/1179/66699
https://gitbook.curiouser.top/origin/pulsar-cli.html
https://github.com/majusko/pulsar-java-spring-boot-starter
https://github.com/majusko/java-pulsar-example
添加依赖
因为当前项目JDK为8,和腾讯云的pulsar版本限制,此处对接依赖为以下几个:
<!--JDK1.8只支持plusar1.0.7的版本-->
<dependency>
<groupId>io.github.majusko</groupId>
<artifactId>pulsar-java-spring-boot-starter</artifactId>
<version>1.0.7</version>
</dependency>
<!--pulsar不支持2.8.0以上的版本,否则报错No recommended schema for decimal (scale is required)-->
<dependency>
<groupId>org.apache.pulsar</groupId>
<artifactId>pulsar-client-all</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.pulsar</groupId>
<artifactId>pulsar-client-original</artifactId>
<version>2.8.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.projectreactor/reactor-core -->
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.5.1</version>
</dependency>
配置接入信息
pulsar:
# 命名空间名称
namespace: namespace_java
# 服务接入地址
service-url: http://pulsar-xxx.tdmq.ap-gz.public.tencenttdmq.com:8080
# 授权角色密钥
token-auth-value: eyJrZXlJZC....
# 集群名称
tenant: pulsar-xxx
以上两步按照腾讯云的SDK对接即可。
消息生产者配置
配置消息的topic,需要提前在腾讯云上创建topic
@Configuration
public class PulsarProducerConfiguration {
// 此次注意如果是String类型的template只能发送string结构的消息体 如果消息体为实体类需要在此处对应设置
@Bean
public ProducerFactory producerFactory() {
return new ProducerFactory()
.addProducer(MqConstants.COMMENT_TOPIC, String.class)
.addProducer(MqConstants.TEST_TOPIC, Entity.class)
.addProducer(MqConstants.SAVE_PLAYER_TOPIC, String.class);
}
}
生产消息
@Component
@RequiredArgsConstructor
@Slf4j
public class PulsarUtil {
// 此次注意如果是String类型的template只能发送string结构的消息体
private final PulsarTemplate<String> pulsarTemplate;
private final PulsarTemplate<Entity> pulsarTemplateEntity;
/**
* 发送异步消息:评论数据
*/
@SneakyThrows
public void sendComment(String topic, Comment msg) {
log.info("mq发送消息:保存评论:topic={},msg={}", topic, JSONUtil.toJsonStr(msg));
msg.getRoom().setLastLiveTime(null);
pulsarTemplate.send(topic, JSONUtil.toJsonStr(msg));
}
/**
* 发送异步消息:保存玩家
*/
@SneakyThrows
public void sendSavePlayer(String topic, Comment msg) {
log.info("mq发送消息:保存玩家:topic={},msg={}", topic, JSONUtil.toJsonStr(msg));
msg.getRoom().setLastLiveTime(null);
pulsarTemplate.send(topic, JSONUtil.toJsonStr(msg));
}
}
消息消费者
@Component
@Slf4j
@RequiredArgsConstructor
public class PulsarListener {
public AtomicBoolean classReceived = new AtomicBoolean(false);
@PulsarConsumer(subscriptionType = SubscriptionType.Key_Shared,
topic = MqConstants.SAVE_PLAYER_TOPIC,
subscriptionName = MqConstants.SAVE_PLAYER_SUBSCRIPTION,
clazz = String.class)
public void savePlayer(String json) {
log.info("mq接收消息:topic={},msg={}", MqConstants.SAVE_PLAYER_TOPIC, json);
try {
Comment comment = JSONUtil.toBean(json, Comment.class);
// 处理对应的业务需求
}catch (Exception e){
log.error("mq处理消息异常:{}", JSONUtil.toJsonStr(e));
}
classReceived.set(true); //消息确认.此处业务场景为了mq不堆积消息,且数据可丢弃的情况下
}
}
消息异常监听器
@Slf4j
@Component
public class PulsarErrorHandler {
private final ConsumerAggregator aggregator;
public PulsarErrorHandler(ConsumerAggregator aggregator) {
this.aggregator = aggregator;
}
@EventListener(ApplicationReadyEvent.class)
public void pulsarErrorHandler() {
aggregator.onError(failedMessage -> failedMessage.getException().printStackTrace());
}
}
常量配置
public final class MqConstants {
/**
* 评论数据持久化主题
*/
public static final String COMMENT_TOPIC = "comment-topic-json";
/**
* 评论数据订阅者
*/
public static final String COMMENT_SUBSCRIPTION = "comment-subscription-Key_Shared";
/**
* 保存玩家持久化主题
*/
public static final String SAVE_PLAYER_TOPIC = "save-player-topic-json";
/**
* 保存玩家订阅者
*/
public static final String SAVE_PLAYER_SUBSCRIPTION = "save-player-subscription-Key_Shared";
}