网关重启数据失效适配

This commit is contained in:
huangweixiong 2022-08-03 14:24:35 +08:00
parent a4e6dad451
commit 04db7c6dc5
4 changed files with 161 additions and 5 deletions

View File

@ -0,0 +1,9 @@
package io.renren.modules.gateway.dao;
import io.renren.common.dao.BaseDao;
import io.renren.modules.gateway.entity.ApiCountHistoryEntity;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ApiCountHistoryDao extends BaseDao<ApiCountHistoryEntity> {
}

View File

@ -0,0 +1,41 @@
package io.renren.modules.gateway.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.renren.common.entity.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* 数据同步算法
* 数据库需要存两个值 1: 上一次来监控系统拉取的 "历史调用总数" A每次拉取都覆盖
* 2. 第二个值拉取"历史调用总数"A1后跟存储的"上一次来监控系统拉取的 历史调用总数"A比较
* 如果新拉取的(A1)较小(代表了网关重启了)先把"上一次拉取的 历史调用总数"A存储起来
* 每次出现这种情况都存储一份记做 B1B2, ... Bn 存储完之后使用A1的值覆盖A
* 最终界面展示"历史调用总数"值的算法B1 + B2 +... + Bn + A
*
* 实体类A对应currentCountB对应historyCount
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName(value = "t_api_count_history", autoResultMap = true)
public class ApiCountHistoryEntity extends BaseEntity implements Serializable {
/**
* 数据版本递增
*/
private Long version;
/**
* 当前数据量
*/
private Long currentCount;
/**
* 历史数据量
*/
private Long historyCount;
}

View File

@ -1,16 +1,17 @@
package io.renren.modules.gateway.service;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.renren.modules.gateway.dao.ApiCountHistoryDao;
import io.renren.modules.gateway.entity.ApiCountHistoryEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
@Service
public class MonitorServiceV2 {
@ -21,7 +22,10 @@ public class MonitorServiceV2 {
@Autowired
private RestTemplate restTemplate;
void fetchCallCount(){
@Autowired
private ApiCountHistoryDao apiCountHistoryDao;
public void fetchCallCount(){
Long currentTime = System.currentTimeMillis() / 1000;
String query = "sum(apigateway_http_status)";
String url = gatewayDomain + "/juapi/metrics/api/v1/query?query={query}" + "&time=" + currentTime.toString();
@ -32,7 +36,76 @@ public class MonitorServiceV2 {
if (data != null) {
List<HashMap> result = (List) data.get("result");
if (result.size() == 1) {
HashMap map = result.get(0);
List value = (List) map.get("value");
if (value.size() == 2) {
String count = (String) value.get(1);
long currentCount = Long.parseLong(count);
handleDataCompare(currentCount);
}
}
}
}
/**
** 数据同步算法
* * 数据库需要存两个值 1: 上一次来监控系统拉取的 "历史调用总数" A每次拉取都覆盖
* * 2. 第二个值拉取"历史调用总数"A1后跟存储的"上一次来监控系统拉取的 历史调用总数"A比较
* * 如果新拉取的(A1)较小(代表了网关重启了)先把"上一次拉取的 历史调用总数"A存储起来
* * 每次出现这种情况都存储一份记做 B1B2, ... Bn 存储完之后使用A1的值覆盖A
* * 最终界面展示"历史调用总数"值的算法B1 + B2 +... + Bn + A
*
* @param currentCount 网关那边当前的总数
*/
public void handleDataCompare(Long currentCount) {
LambdaQueryWrapper<ApiCountHistoryEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.orderByDesc(ApiCountHistoryEntity::getVersion)
.last("LIMIT 1");
ApiCountHistoryEntity apiCountHistoryEntity = apiCountHistoryDao.selectOne(queryWrapper);
if (apiCountHistoryEntity == null){
apiCountHistoryEntity = new ApiCountHistoryEntity();
apiCountHistoryEntity.setCurrentCount(currentCount);
apiCountHistoryEntity.setHistoryCount(0L);
apiCountHistoryEntity.setVersion(0L);
apiCountHistoryDao.insert(apiCountHistoryEntity);
}else if (currentCount < apiCountHistoryEntity.getCurrentCount()){
//保存旧值
apiCountHistoryEntity.setHistoryCount(apiCountHistoryEntity.getCurrentCount());
apiCountHistoryEntity.setCreateDate(new Date());
apiCountHistoryDao.updateById(apiCountHistoryEntity);
//新增记录
ApiCountHistoryEntity newHistoryEntity = new ApiCountHistoryEntity();
newHistoryEntity.setCurrentCount(currentCount);
newHistoryEntity.setHistoryCount(0L);
newHistoryEntity.setVersion(apiCountHistoryEntity.getVersion() + 1);
apiCountHistoryDao.insert(newHistoryEntity);
}else if (currentCount > apiCountHistoryEntity.getCurrentCount()){//相等时没有必要更新
apiCountHistoryEntity.setCurrentCount(currentCount);
apiCountHistoryDao.updateById(apiCountHistoryEntity);
}
}
/**
* 查询历史总数
* @return
*/
public Long getCallCount(){
LambdaQueryWrapper<ApiCountHistoryEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.orderByDesc(ApiCountHistoryEntity::getVersion)
.last("LIMIT 1");
ApiCountHistoryEntity apiCountHistoryEntity = apiCountHistoryDao.selectOne(queryWrapper);
if (apiCountHistoryEntity != null) {
Long currentCount = apiCountHistoryEntity.getCurrentCount();
QueryWrapper<ApiCountHistoryEntity> hisQueryWrapper = new QueryWrapper<>();
hisQueryWrapper.select("sum(history_count) as history_count");
ApiCountHistoryEntity historyEntity = apiCountHistoryDao.selectOne(hisQueryWrapper);
if (historyEntity != null) {
return historyEntity.getHistoryCount() + currentCount;
}
}
return 0L;
}
}

View File

@ -0,0 +1,33 @@
package io.renren;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.renren.modules.gateway.service.MonitorServiceV2;
import io.renren.modules.processForm.service.ApiGatewayService;
import io.renren.modules.resource.dao.ResourceDao;
import io.renren.modules.resource.entity.ResourceEntity;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GatewaySyncServiceTest {
@Autowired
private MonitorServiceV2 monitorServiceV2;
@Test
public void syncCount() {
Integer[] dataSet = {10, 11, 50, 30, 44, 2,44,9};
for (Integer count : dataSet) {
monitorServiceV2.handleDataCompare(Long.valueOf(count));
}
}
}