Commit 89f0c9cf by 岳建彬

add Cursor 快速解决客户端重连问题示例

parent 896af18c
# Spring Boot 集成 EMQX 客户端重连与订阅恢复
# Spring Boot 集成 EMQX 客户端重连与订阅恢复
> **场景**: 解决微服务重启后 EMQX 客户端连接断开,但服务端订阅状态不同步的问题
>
> **技术栈**: Spring Boot + MQTT + EMQX
>
> **作者**: 基于 Cursor AI 对话整理
> **日期**: 2025-06-26
---
## 问题描述
在微服务架构中,当云服务重启后,会出现以下问题:
- EMQX 服务端客户端连接断开
- 订阅者在服务端依然存在
- 客户端重连后订阅状态不同步
## 使用 Cursor 的解决过程
### 1. 问题诊断 Prompt
```
@/micro-cloud-adapter cloud 服务重启后 会 emqx 服务端 客户端断开了连接,但是订阅者在服务端还依然存在,该如何解决
```
### 2. 代码分析与解决方案
#### 问题根因分析
Cursor 分析后发现主要问题:
1. **clientId 使用 UUID**: 每次服务重启都会生成新的 clientId,导致 EMQX 无法识别同一客户端
2. **cleanSession 设置**: 会话持久化配置不当
3. **缺少重连机制**: 没有在重连后立即恢复订阅的机制
#### 解决方案代码
**优化后的 MqttConfig 配置类**
```java
@Configuration
public class MqttConfig {
@Value("${spring.application.name}")
private String applicationName;
@Autowired
private MqttTopicService mqttTopicService;
/**
* 生成固定的 clientId,基于应用名和主机信息
* 确保服务重启后 clientId 保持一致
*/
private String getFixedClientId() {
try {
String hostName = InetAddress.getLocalHost().getHostName();
return applicationName + "-" + hostName + "-service";
} catch (Exception e) {
return applicationName + "-service";
}
}
@Bean
public MqttPahoClientFactory mqttClientFactory() {
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
MqttConnectOptions options = new MqttConnectOptions();
// 关键配置:使用固定 clientId
options.setClientId(getFixedClientId());
options.setCleanSession(false); // 保持会话持久化
options.setAutomaticReconnect(true); // 自动重连
options.setKeepAliveInterval(60);
options.setConnectionTimeout(30);
factory.setConnectionOptions(options);
return factory;
}
}
```
**添加连接状态监听器**
```java
@Component
@Slf4j
public class MqttConnectionCallback implements MqttCallback {
@Autowired
private MqttTopicService mqttTopicService;
@Override
public void connectionLost(Throwable cause) {
log.warn("MQTT连接丢失: {}", cause.getMessage());
}
@Override
public void connectComplete(boolean reconnect, String serverURI) {
if (reconnect) {
log.info("MQTT重连成功,开始恢复订阅");
// 重连后立即恢复订阅
restoreSubscriptions();
}
}
private void restoreSubscriptions() {
try {
List<String> topics = mqttTopicService.getAllTopics();
// 重新订阅所有主题
mqttTopicService.subscribeTopics(topics);
log.info("订阅恢复完成,共恢复 {} 个主题", topics.size());
} catch (Exception e) {
log.error("恢复订阅失败", e);
}
}
}
```
### 3. 效果验证
使用 Cursor 生成的测试用例:
```java
@Test
public void testReconnectAndSubscribe() {
// 模拟服务重启
mqttClient.disconnect();
// 验证重连后订阅状态
mqttClient.connect();
// 检查订阅是否正常恢复
List<String> activeTopics = mqttTopicService.getActiveSubscriptions();
assertThat(activeTopics).isNotEmpty();
}
```
## 关键配置总结
| 配置项 | 推荐值 | 说明 |
|--------|--------|------|
| `clientId` | 基于应用名+主机名 | 确保重启后一致性 |
| `cleanSession` | `false` | 保持会话持久化 |
| `automaticReconnect` | `true` | 启用自动重连 |
| `keepAliveInterval` | `60` | 心跳间隔 |
## 使用体验
### Cursor 的优势
- 快速定位问题根因
- 提供完整的代码解决方案
- 自动生成相关测试用例
### 注意事项
- 需要根据实际项目结构调整包名和类名
- SSL 配置需要根据实际证书路径调整
- 监听器注册需要确保在 Spring 容器中正确装配
---
## 相关资源
- [EMQX 官方文档](https://www.emqx.io/docs)
- [Spring Integration MQTT](https://docs.spring.io/spring-integration/reference/html/mqtt.html)
- [Eclipse Paho MQTT Client](https://www.eclipse.org/paho/clients/java/)
- [完整对话记录](./original-conversations/cursor-emqx-mqtt-reconnect-conversation.md) - 查看与 Cursor AI 的完整问题分析过程
## 扩展思考
1. **集群环境下的 clientId 策略**
2. **订阅主题的动态管理**
3. **消息重复处理机制**
4. **监控与告警集成**
---
## 💡 学习建议
想要了解完整的问题分析过程?点击查看 [原始 Cursor 对话记录](./original-conversations/cursor-emqx-mqtt-reconnect-conversation.md),包含:
- AI 的完整分析思路
- 多轮问题诊断过程
- 代码生成和优化过程
- 测试验证方案推导
\ No newline at end of file
# Backend 案例集合
> 收集后端开发中使用 Cursor 的典型案例和最佳实践
## Java 案例
### 1. Spring Boot 集成 EMQX 客户端重连与订阅恢复
**文件**: `spring-boot-emqx-integration.md`
**场景**: 解决微服务重启后 EMQX 客户端连接断开,但服务端订阅状态不同步的问题
**关键技术**:
- Spring Boot + MQTT 集成
- 客户端重连机制
- 订阅状态恢复
- 连接监听器实现
**使用收益**:
- 快速定位 MQTT 连接问题根因
- 自动生成完整的解决方案代码
- 提供测试验证方案
---
## 添加新案例
如需添加新的后端案例,请遵循以下格式:
1. 文件命名:`技术栈-具体场景.md`
2. 内容结构:
- 问题描述
- 使用 Cursor 的解决过程
- 关键代码片段
- 效果验证
- 使用体验总结
## 技术栈覆盖
- [x] Spring Boot + MQTT
- [ ] Spring Cloud 微服务
- [ ] MyBatis Plus 数据库操作
- [ ] Redis 缓存集成
- [ ] RabbitMQ 消息队列
- [ ] ElasticSearch 搜索
- [ ] Docker 容器化
\ No newline at end of file
# 原始对话备份
> 此文件夹保存与 Cursor AI 的完整对话记录,供参考和学习使用
## 文件说明
### `cursor-emqx-mqtt-reconnect-conversation.md`
- **原始问题**: 解决 EMQX 服务端客户端断开问题
- **对话日期**: 2025-06-26
- **技术栈**: Spring Boot + MQTT + EMQX
- **解决方案**: 客户端重连与订阅恢复机制
## 使用说明
1. 这些文件保存了完整的 Cursor AI 对话过程
2. 可以点击文件链接查看详细的问题分析过程
3. 包含了 AI 的思考过程和多轮对话交互
4. 适用于:
- 学习 Cursor AI 的使用技巧
- 了解问题分析的完整思路
- 复现类似问题的解决过程
## 文件结构
```
original-conversations/
├── README.md # 本说明文件
├── cursor-emqx-mqtt-reconnect-conversation.md # EMQX 重连问题完整对话
└── [其他对话备份...]
```
---
**注意**: 这些文件包含完整的 AI 对话导出,可能包含调试信息和多次尝试的过程,与 `cases/backend/` 中的精简案例不同。
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment