mqttClient是一个储存在内存中的对象,一旦服务器重启或者项目发版,必须让刚刚正在工作的消费方重新启动起来
同时我们需要将这些对象储存起来,方便我们手动关闭监听
一个仓库+一个线程哨兵
上代码
package com.datacvg.config;
import com.datacvg.dao.ExchangeMqWithDatabaseMapper;
import com.datacvg.mqtt.DatasourceCrossClient;
import com.datacvg.vo.ExchangeMqPushDatabaseVo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.*;
/**
* @Author: 商朝
* @Date: 2021.4.15
* @Function: 正在运行客户端的仓库+重启服务器扫描正在运行的服务重启并入库
*/
@Component
public class RestartMqttClientConfig {
private final HashMap<String,DatasourceCrossClient> runningClient =new HashMap<>();
@Autowired
ExchangeMqWithDatabaseMapper exchangeMqWithDatabaseMapper;
@Autowired
RestartMqttClientConfig checkStock;
@PostConstruct
public void restartListen(){
try {
//查出正在运行的服务
List<ExchangeMqPushDatabaseVo> listClient = exchangeMqWithDatabaseMapper.queryAllRunningClient();
//用于储存已经开服务的客户端和datasourceId的对应关系
Map<String, DatasourceCrossClient> tempDatasourceCrossClient = new HashMap<>();
//存放clientId正在被占用的客户端(假如有两个clientId重复 会停掉前者)-即将要停掉的服务
List<String> listWillBeStopedMq = new LinkedList<>();
//哨兵站岗
new Thread(new CheckStock(checkStock,exchangeMqWithDatabaseMapper)).start();
if (CollectionUtils.isEmpty(listClient)) return;
for (ExchangeMqPushDatabaseVo mqPushVO : listClient) {
DatasourceCrossClient crossClient = new DatasourceCrossClient();
//启动服务
crossClient.crossSensationLinkListenAndInsert(mqPushVO.getMqUsername(), mqPushVO.getMqPassword(), mqPushVO.getMqUrl(), mqPushVO.getMqTopicname(), mqPushVO.getMqClientId(), mqPushVO.getTableName());
//添加对应关系
tempDatasourceCrossClient.put(mqPushVO.getDatasourceId(), crossClient);
}
if (tempDatasourceCrossClient.size() != 0) {
Set<Map.Entry<String, DatasourceCrossClient>> entries = tempDatasourceCrossClient.entrySet();
for (Map.Entry<String, DatasourceCrossClient> entry : entries) {
if (!entry.getValue().getClientIdCouldBeUsed()) {
listWillBeStopedMq.add(entry.getKey());
} else {
//入库
setRunningClient(entry.getKey(), entry.getValue());
}
}
}
if (listWillBeStopedMq.size() != 0) {
//改表
exchangeMqWithDatabaseMapper.updateToStop(listWillBeStopedMq);
}
}catch (Exception e){
e.printStackTrace();
}
}
public HashMap<String,DatasourceCrossClient> getRunningClient(){
return this.runningClient;
}
public void setRunningClient(String sourceObject,DatasourceCrossClient crossClient){
this.runningClient.put(sourceObject,crossClient);
}
public void removeRunningClient(List<String> sourceObject){
for (String s : sourceObject) {
this.runningClient.remove(s);
}
}
}
/**
*
*每隔三秒检索一次
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
class CheckStock implements Runnable{
RestartMqttClientConfig stock;
ExchangeMqWithDatabaseMapper exchangeMqWithDatabaseMapper;
public void run() {
while (true){
try {
Thread.sleep(3000);
LinkedList<String> list =new LinkedList<>();
if(stock.getRunningClient().isEmpty()){
continue;
}
Set<Map.Entry<String, DatasourceCrossClient>> entries = stock.getRunningClient().entrySet();
List<String> willBeStoped = exchangeMqWithDatabaseMapper.queryAllStoppedClient();
if(CollectionUtils.isEmpty(willBeStoped)){
continue;
}
for (String s : willBeStoped) {
if(stock.getRunningClient().containsKey(s)){
DatasourceCrossClient datasourceCrossClient = stock.getRunningClient().get(s);
try {
datasourceCrossClient.getMqttClient().disconnect();
datasourceCrossClient.getMqttClient().close();
}catch (Exception e){
e.printStackTrace();
}
}
}
if(entries.size()!=0){
for (Map.Entry<String, DatasourceCrossClient> entry : entries) {
if(!entry.getValue().getClientIdCouldBeUsed()){
list.add(entry.getKey());
}
}
}
if(list.size()!=0){
stock.removeRunningClient(list);
exchangeMqWithDatabaseMapper.updateToStop(list);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}