From d3e56bf0815ce5f232d085d2e5b082f24180aa09 Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Mon, 7 Jul 2025 21:46:48 +0800 Subject: [PATCH 01/17] handler --- .../admin/config/ClusterConfiguration.java | 3 + .../admin/config/StandaloneConfiguration.java | 5 +- .../admin/controller/InstanceController.java | 24 ++- .../cluster/service/ShenyuClusterService.java | 9 +- .../standalone/ShenyuStandaloneService.java | 11 +- .../admin/model/dto/InstanceBeatInfoDTO.java | 119 +++++++++++++++ .../admin/model/entity/InstanceInfoDO.java | 22 ++- .../shenyu/admin/model/vo/InstanceInfoVO.java | 48 +++++- .../admin/service/InstanceInfoService.java | 11 ++ .../service/impl/InstanceCheckService.java | 141 ++++++++++++++++++ .../service/impl/InstanceInfoServiceImpl.java | 28 ++++ 11 files changed, 415 insertions(+), 6 deletions(-) create mode 100644 shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceBeatInfoDTO.java create mode 100644 shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/ClusterConfiguration.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/ClusterConfiguration.java index bcb7b1b982b7..da8a63c63124 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/ClusterConfiguration.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/ClusterConfiguration.java @@ -23,6 +23,7 @@ import org.apache.shenyu.admin.mode.cluster.filter.ClusterForwardFilter; import org.apache.shenyu.admin.mode.cluster.service.ClusterSelectMasterService; import org.apache.shenyu.admin.mode.cluster.service.ShenyuClusterService; +import org.apache.shenyu.admin.service.impl.InstanceCheckService; import org.apache.shenyu.admin.service.impl.UpstreamCheckService; import org.apache.shenyu.admin.service.manager.LoadServiceDocEntry; import org.slf4j.Logger; @@ -58,11 +59,13 @@ public class ClusterConfiguration { @ConditionalOnMissingBean public ShenyuRunningModeService shenyuRunningModeService(final ClusterSelectMasterService shenyuClusterSelectMasterService, final UpstreamCheckService upstreamCheckService, + final InstanceCheckService instanceCheckService, final LoadServiceDocEntry loadServiceDocEntry, final ClusterProperties clusterProperties) { LOGGER.info("starting in cluster mode ..."); return new ShenyuClusterService(shenyuClusterSelectMasterService, upstreamCheckService, + instanceCheckService, loadServiceDocEntry, clusterProperties ); diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/StandaloneConfiguration.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/StandaloneConfiguration.java index 728cd50ffbf9..50fb54b76751 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/StandaloneConfiguration.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/StandaloneConfiguration.java @@ -19,6 +19,7 @@ import org.apache.shenyu.admin.mode.ShenyuRunningModeService; import org.apache.shenyu.admin.mode.standalone.ShenyuStandaloneService; +import org.apache.shenyu.admin.service.impl.InstanceCheckService; import org.apache.shenyu.admin.service.impl.UpstreamCheckService; import org.apache.shenyu.admin.service.manager.LoadServiceDocEntry; import org.slf4j.Logger; @@ -47,11 +48,13 @@ public class StandaloneConfiguration { @ConditionalOnProperty(value = {"shenyu.cluster.enabled"}, havingValue = "false", matchIfMissing = true) @ConditionalOnMissingBean public ShenyuRunningModeService shenyuRunningModeService(final UpstreamCheckService upstreamCheckService, + final InstanceCheckService instanceCheckService, final LoadServiceDocEntry loadServiceDocEntry) { LOGGER.info("starting in standalone mode ..."); return new ShenyuStandaloneService( upstreamCheckService, - loadServiceDocEntry + loadServiceDocEntry, + instanceCheckService ); } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java index a2d521882153..7edc377766e0 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java @@ -19,6 +19,7 @@ import jakarta.validation.constraints.NotNull; import org.apache.shenyu.admin.aspect.annotation.RestApi; +import org.apache.shenyu.admin.model.dto.InstanceBeatInfoDTO; import org.apache.shenyu.admin.model.page.CommonPager; import org.apache.shenyu.admin.model.page.PageParameter; import org.apache.shenyu.admin.model.query.InstanceQuery; @@ -27,10 +28,12 @@ import org.apache.shenyu.admin.model.vo.InstanceInfoVO; import org.apache.shenyu.admin.service.InstanceInfoService; import org.apache.shenyu.admin.service.PageService; +import org.apache.shenyu.admin.service.impl.InstanceCheckService; import org.apache.shenyu.admin.utils.ShenyuResultMessage; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; /** @@ -41,8 +44,11 @@ public class InstanceController implements PagedController pageService() { diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mode/cluster/service/ShenyuClusterService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mode/cluster/service/ShenyuClusterService.java index 0430202159d9..87a87781a9c2 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mode/cluster/service/ShenyuClusterService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mode/cluster/service/ShenyuClusterService.java @@ -19,6 +19,7 @@ import org.apache.shenyu.admin.config.properties.ClusterProperties; import org.apache.shenyu.admin.mode.ShenyuRunningModeService; +import org.apache.shenyu.admin.service.impl.InstanceCheckService; import org.apache.shenyu.admin.service.impl.UpstreamCheckService; import org.apache.shenyu.admin.service.manager.LoadServiceDocEntry; import org.apache.shenyu.common.concurrent.ShenyuThreadFactory; @@ -43,9 +44,12 @@ public class ShenyuClusterService implements ShenyuRunningModeService { private final ScheduledExecutorService executorService; private final ClusterProperties clusterProperties; + + private final InstanceCheckService instanceCheckService; public ShenyuClusterService(final ClusterSelectMasterService shenyuClusterSelectMasterService, final UpstreamCheckService upstreamCheckService, + final InstanceCheckService instanceCheckService, final LoadServiceDocEntry loadServiceDocEntry, final ClusterProperties clusterProperties) { this.shenyuClusterSelectMasterService = shenyuClusterSelectMasterService; @@ -54,6 +58,7 @@ public ShenyuClusterService(final ClusterSelectMasterService shenyuClusterSelect this.clusterProperties = clusterProperties; this.executorService = new ScheduledThreadPoolExecutor(1, ShenyuThreadFactory.create("master-selector", true)); + this.instanceCheckService = instanceCheckService; } /** @@ -85,7 +90,8 @@ private void doSelectMaster(final String host, final String port, final String c // start upstream check task upstreamCheckService.setup(); - + + instanceCheckService.setup(); // load api loadServiceDocEntry.loadApiDocument(); @@ -106,6 +112,7 @@ private void doSelectMaster(final String host, final String port, final String c LOG.error("select master error", e); // close the upstream check service upstreamCheckService.close(); + instanceCheckService.close(); String message = String.format("renew master fail, %s", e.getMessage()); throw new ShenyuException(message); diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mode/standalone/ShenyuStandaloneService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mode/standalone/ShenyuStandaloneService.java index ebb11c448892..36e441626edc 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mode/standalone/ShenyuStandaloneService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mode/standalone/ShenyuStandaloneService.java @@ -18,6 +18,7 @@ package org.apache.shenyu.admin.mode.standalone; import org.apache.shenyu.admin.mode.ShenyuRunningModeService; +import org.apache.shenyu.admin.service.impl.InstanceCheckService; import org.apache.shenyu.admin.service.impl.UpstreamCheckService; import org.apache.shenyu.admin.service.manager.LoadServiceDocEntry; @@ -26,17 +27,24 @@ public class ShenyuStandaloneService implements ShenyuRunningModeService { private final UpstreamCheckService upstreamCheckService; private final LoadServiceDocEntry loadServiceDocEntry; + + private final InstanceCheckService instanceCheckService; public ShenyuStandaloneService(final UpstreamCheckService upstreamCheckService, - final LoadServiceDocEntry loadServiceDocEntry) { + final LoadServiceDocEntry loadServiceDocEntry, + final InstanceCheckService instanceCheckService) { this.upstreamCheckService = upstreamCheckService; this.loadServiceDocEntry = loadServiceDocEntry; + this.instanceCheckService = instanceCheckService; } @Override public void start(final String host, final int port, final String contextPath) { // start upstream check task upstreamCheckService.setup(); + + instanceCheckService.setup(); + // load api loadServiceDocEntry.loadApiDocument(); } @@ -44,5 +52,6 @@ public void start(final String host, final int port, final String contextPath) { @Override public void shutdown() { upstreamCheckService.close(); + instanceCheckService.close(); } } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceBeatInfoDTO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceBeatInfoDTO.java new file mode 100644 index 000000000000..6b68794c1267 --- /dev/null +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceBeatInfoDTO.java @@ -0,0 +1,119 @@ +package org.apache.shenyu.admin.model.dto; + +public class InstanceBeatInfoDTO { + /** + * instance ip. + */ + private String instanceIp; + + /** + * instance port. + */ + private String instancePort; + + /** + * instance type. + */ + private String instanceType; + + /** + * instance info. + */ + private String instanceInfo; + + /** + * namespaceId. + */ + private String namespaceId; + + /** + * get instanceIp. + * + * @return instanceIp + */ + public String getInstanceIp() { + return instanceIp; + } + + /** + * set instanceIp. + * + * @param instanceIp instanceIp + */ + public void setInstanceIp(final String instanceIp) { + this.instanceIp = instanceIp; + } + + /** + * get instancePort. + * + * @return instancePort + */ + public String getInstancePort() { + return instancePort; + } + + /** + * set instancePort. + * + * @param instancePort instancePort + */ + public void setInstancePort(final String instancePort) { + this.instancePort = instancePort; + } + + /** + * get instanceType. + * + * @return instanceType + */ + public String getInstanceType() { + return instanceType; + } + + /** + * set instanceType. + * + * @param instanceType instanceType + */ + public void setInstanceType(final String instanceType) { + this.instanceType = instanceType; + } + + /** + * get instanceInfo. + * + * @return instanceInfo + */ + public String getInstanceInfo() { + return instanceInfo; + } + + /** + * set instanceInfo. + * + * @param instanceInfo instanceInfo + */ + public void setInstanceInfo(final String instanceInfo) { + this.instanceInfo = instanceInfo; + } + + /** + * get namespaceId. + * + * @return namespaceId + */ + public String getNamespaceId() { + return namespaceId; + } + + /** + * set namespaceId. + * + * @param namespaceId namespaceId + */ + public void setNamespaceId(final String namespaceId) { + this.namespaceId = namespaceId; + } + +} diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java index 30adf5f15825..8f9986c81622 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java @@ -39,6 +39,8 @@ public final class InstanceInfoDO extends BaseDO { private Integer instanceState; private String namespaceId; + + private long lastHeartBeatTime; public InstanceInfoDO() { @@ -228,7 +230,25 @@ public String getNamespaceId() { public void setNamespaceId(final String namespaceId) { this.namespaceId = namespaceId; } - + + /** + * get lastHeartBeatTime. + * + * @return lastHeartBeatTime + */ + public long getLastHeartBeatTime() { + return lastHeartBeatTime; + } + + /** + * set lastHeartBeatTime. + * + * @param lastHeartBeatTime lastHeartBeatTime + */ + public void setLastHeartBeatTime(long lastHeartBeatTime) { + this.lastHeartBeatTime = lastHeartBeatTime; + } + /** * builder. * diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceInfoVO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceInfoVO.java index be41fe52b9b8..cefe01aeb2e7 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceInfoVO.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceInfoVO.java @@ -52,6 +52,11 @@ public class InstanceInfoVO implements Serializable { * namespaceId. */ private String namespaceId; + + /** + * status. + */ + private int instanceState; /** * created time. @@ -62,6 +67,11 @@ public class InstanceInfoVO implements Serializable { * updated time. */ private Timestamp dateUpdated; + + /** + * lastBeat time. + */ + private long lastHeartBeatTime; /** * get instanceIp. @@ -188,7 +198,43 @@ public Timestamp getDateUpdated() { public void setDateUpdated(final Timestamp dateUpdated) { this.dateUpdated = dateUpdated; } - + + /** + * get instanceState. + * + * @return instanceState + */ + public int getInstanceState() { + return instanceState; + } + + /** + * set instanceState. + * + * @param instanceState instanceState + */ + public void setInstanceState(int instanceState) { + this.instanceState = instanceState; + } + + /** + * get lastHeartBeatTime. + * + * @return lastHeartBeatTime + */ + public long getLastHeartBeatTime() { + return lastHeartBeatTime; + } + + /** + * set lastHeartBeatTime. + * + * @param lastHeartBeatTime lastHeartBeatTime + */ + public void setLastHeartBeatTime(long lastHeartBeatTime) { + this.lastHeartBeatTime = lastHeartBeatTime; + } + @Override public boolean equals(final Object o) { if (this == o) { diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/InstanceInfoService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/InstanceInfoService.java index 78cbb09d5646..56a51c9a23c2 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/InstanceInfoService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/InstanceInfoService.java @@ -23,6 +23,8 @@ import org.apache.shenyu.admin.model.query.InstanceQueryCondition; import org.apache.shenyu.admin.model.vo.InstanceInfoVO; +import java.util.List; + public interface InstanceInfoService extends PageService { /** @@ -31,6 +33,13 @@ public interface InstanceInfoService extends PageService listByPage(InstanceQuery instanceQuery); + + List list(); /** * findById. diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java new file mode 100644 index 000000000000..caac6fd74251 --- /dev/null +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java @@ -0,0 +1,141 @@ +package org.apache.shenyu.admin.service.impl; + +import com.google.common.collect.Lists; +import jakarta.annotation.PreDestroy; +import org.apache.shenyu.admin.model.dto.InstanceBeatInfoDTO; +import org.apache.shenyu.admin.model.vo.InstanceInfoVO; +import org.apache.shenyu.admin.service.InstanceInfoService; +import org.apache.shenyu.common.concurrent.ShenyuThreadFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * This is the client check service. + */ +@Component +public class InstanceCheckService { + + private static final Logger LOG = LoggerFactory.getLogger(UpstreamCheckService.class); + + private ScheduledThreadPoolExecutor executor; + + private ScheduledFuture scheduledFuture; + + private final int scheduledTime; + + private ConcurrentHashMap instanceHealthBeatInfo; + + private long instanceHeartBeatTimeOut; + + private long deleteTimeout; + + private InstanceInfoService instanceInfoService; + + + public InstanceCheckService(ScheduledThreadPoolExecutor executor, ScheduledFuture scheduledFuture, int scheduledTime, ConcurrentHashMap instanceHealthBeatInfo, long instanceHeartBeatTimeOut, long deleteTimeout, InstanceInfoService instanceInfoService) { + this.executor = executor; + this.scheduledFuture = scheduledFuture; + this.scheduledTime = scheduledTime; + this.instanceHealthBeatInfo = instanceHealthBeatInfo; + this.instanceHeartBeatTimeOut = instanceHeartBeatTimeOut; + this.deleteTimeout = deleteTimeout; + this.instanceInfoService = instanceInfoService; + } + + /** + * Set up. + */ + public void setup() { + this.fetchInstanceData(); + executor = new ScheduledThreadPoolExecutor(1, ShenyuThreadFactory.create("scheduled-instance-task", false)); + scheduledFuture = executor.scheduleWithFixedDelay(this::scheduled, 10, scheduledTime, TimeUnit.SECONDS); + } + + /** + * fetch instance status data from db. + */ + public void fetchInstanceData() { + List list = instanceInfoService.list(); + list.forEach(instanceInfoVO -> { + String instanceKey = getInstanceKey(instanceInfoVO); + instanceHealthBeatInfo.put(instanceKey,instanceInfoVO); + }); + } + + public String getInstanceKey(InstanceInfoVO instanceInfoVO){ + return instanceInfoVO.getInstanceIp()+":"+instanceInfoVO.getInstancePort()+"@"+instanceInfoVO.getInstanceType()+"#"+instanceInfoVO.getNamespaceId(); + } + + public String getInstanceKey(InstanceBeatInfoDTO instanceBeatInfoDTO){ + return instanceBeatInfoDTO.getInstanceIp()+":"+instanceBeatInfoDTO.getInstancePort()+"@"+instanceBeatInfoDTO.getInstanceType()+"#"+instanceBeatInfoDTO.getNamespaceId(); + } + + public InstanceInfoVO getInstanceHealthBeatInfo(InstanceBeatInfoDTO instanceBeatInfoDTO){ + return instanceHealthBeatInfo.get(getInstanceKey(instanceBeatInfoDTO)); + } + + public void handleBeatInfo(InstanceBeatInfoDTO instanceBeatInfoDTO){ + String instanceKey = getInstanceKey(instanceBeatInfoDTO); + if (instanceHealthBeatInfo.contains(instanceKey)){ + InstanceInfoVO instanceInfoVO = instanceHealthBeatInfo.get(instanceKey); + instanceInfoVO.setLastHeartBeatTime(System.currentTimeMillis()); + }else { + InstanceInfoVO instanceInfoVO = new InstanceInfoVO(); + instanceInfoVO.setInstanceIp(instanceBeatInfoDTO.getInstanceIp()); + instanceInfoVO.setInstanceState(1); + instanceInfoVO.setInstanceInfo(instanceBeatInfoDTO.getInstanceInfo()); + instanceInfoVO.setInstanceType(instanceBeatInfoDTO.getInstanceType()); + instanceInfoVO.setLastHeartBeatTime(System.currentTimeMillis()); + instanceInfoVO.setInstancePort(instanceBeatInfoDTO.getInstancePort()); + instanceInfoVO.setNamespaceId(instanceBeatInfoDTO.getNamespaceId()); + instanceHealthBeatInfo.put(instanceKey,instanceInfoVO); + } + } + + private void scheduled() { + try { + doCheck(); + } catch (Exception e) { + LOG.error("upstream scheduled check error -------- ", e); + } + } + + private void doCheck() { + instanceHealthBeatInfo.values().forEach(instance -> { + if (System.currentTimeMillis() - instance.getLastHeartBeatTime() > instanceHeartBeatTimeOut) { + if (1 == instance.getInstanceState()) { + LOG.info("[instanceHealthInfo]namespace:{},type:{},Ip:{},Port:{} offline!", instance.getNamespaceId(), instance.getInstanceType(), instance.getInstanceIp(), instance.getInstancePort()); + instance.setInstanceState(2); + } + } + if (System.currentTimeMillis() - instance.getLastHeartBeatTime() > deleteTimeout) { + if (2 == instance.getInstanceState()) { + LOG.info("[instanceHealthInfo]namespace:{},type:{},Ip:{},Port:{} deleted!", instance.getNamespaceId(), instance.getInstanceType(), instance.getInstanceIp(), instance.getInstancePort()); + instance.setInstanceState(0); + } + } + }); + } + + public void syncDB(){ + instanceHealthBeatInfo.values().forEach(vo->{ + instanceInfoService.createOrUpdate(vo); + }); + } + /** + * Close relative resource on container destroy. + */ + @PreDestroy + public void close() { + syncDB(); + executor.shutdown(); + } +} diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java index 4c13b9081edb..79aa7f24ff3c 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java @@ -77,12 +77,40 @@ public void createOrUpdate(final InstanceInfoDTO instanceInfoDTO) { instanceInfoMapper.updateById(infoDO); } + @Override + public void createOrUpdate(InstanceInfoVO instanceInfoVO) { + InstanceQuery instanceQuery = new InstanceQuery(); + instanceQuery.setInstanceIp(instanceInfoVO.getInstanceIp()); + instanceQuery.setInstancePort(instanceInfoVO.getInstancePort()); + instanceQuery.setInstanceType(instanceInfoVO.getInstanceType()); + instanceQuery.setNamespaceId(instanceInfoVO.getNamespaceId()); + InstanceInfoDO infoDO = instanceInfoMapper.selectOneByQuery(instanceQuery); + if (Objects.isNull(infoDO)) { + LOG.info("update instance info fail: {}", GsonUtils.getInstance().toJson(instanceInfoVO)); + return; + } + LOG.info("Update instance info: {}", GsonUtils.getInstance().toJson(instanceInfoVO)); + infoDO.setInstanceIp(instanceInfoVO.getInstanceIp()); + infoDO.setInstanceType(instanceInfoVO.getInstanceType()); + infoDO.setInstanceInfo(instanceInfoVO.getInstanceInfo()); + infoDO.setNamespaceId(instanceInfoVO.getNamespaceId()); + infoDO.setDateUpdated(Timestamp.from(Instant.now())); + infoDO.setInstanceState(instanceInfoVO.getInstanceState()); + infoDO.setLastHeartBeatTime(instanceInfoVO.getLastHeartBeatTime()); + instanceInfoMapper.updateById(infoDO); + } + @Override public CommonPager listByPage(final InstanceQuery instanceQuery) { List instanceInfoDOList = instanceInfoMapper.selectByQuery(instanceQuery); return PageResultUtils.result(instanceQuery.getPageParameter(), () -> this.buildInstanceInfoVO(instanceInfoDOList)); } + @Override + public List list() { + return this.buildInstanceInfoVO(instanceInfoMapper.selectAll()); + } + @Override public InstanceInfoVO findById(final String id) { return null; From 2c885a79a6009eeaff701512f2ca38a0dc2a7181 Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Mon, 7 Jul 2025 21:57:11 +0800 Subject: [PATCH 02/17] handler --- .../admin/service/impl/InstanceCheckService.java | 12 +++++------- .../src/main/resources/application-mysql.yml | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java index caac6fd74251..40fdb0019979 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java @@ -40,13 +40,11 @@ public class InstanceCheckService { private InstanceInfoService instanceInfoService; - public InstanceCheckService(ScheduledThreadPoolExecutor executor, ScheduledFuture scheduledFuture, int scheduledTime, ConcurrentHashMap instanceHealthBeatInfo, long instanceHeartBeatTimeOut, long deleteTimeout, InstanceInfoService instanceInfoService) { - this.executor = executor; - this.scheduledFuture = scheduledFuture; - this.scheduledTime = scheduledTime; - this.instanceHealthBeatInfo = instanceHealthBeatInfo; - this.instanceHeartBeatTimeOut = instanceHeartBeatTimeOut; - this.deleteTimeout = deleteTimeout; + public InstanceCheckService(InstanceInfoService instanceInfoService) { + this.scheduledTime = 500; + this.instanceHealthBeatInfo = new ConcurrentHashMap<>(); + this.instanceHeartBeatTimeOut = 500; + this.deleteTimeout = 500; this.instanceInfoService = instanceInfoService; } diff --git a/shenyu-admin/src/main/resources/application-mysql.yml b/shenyu-admin/src/main/resources/application-mysql.yml index 6db63a81d148..41d55b4bc8a5 100755 --- a/shenyu-admin/src/main/resources/application-mysql.yml +++ b/shenyu-admin/src/main/resources/application-mysql.yml @@ -22,7 +22,7 @@ spring: datasource: url: jdbc:mysql://localhost:3306/shenyu?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true username: root - password: passwd4mysql + password: 123 driver-class-name: com.mysql.cj.jdbc.Driver hikari: connection-timeout: 30000 From 3100a43384b6997e42adf85f42f978e1e61075da Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Sat, 12 Jul 2025 14:17:16 +0800 Subject: [PATCH 03/17] commit --- .../config/ShenyuAdminConfiguration.java | 7 + .../admin/controller/InstanceController.java | 6 +- .../admin/model/dto/InstanceInfoDTO.java | 217 ------------- .../admin/model/entity/InstanceInfoDO.java | 23 +- .../instance/InstanceInfoReportEvent.java | 301 ++++++++++++++++++ .../admin/service/InstanceInfoService.java | 8 - .../service/impl/InstanceCheckService.java | 22 ++ .../service/impl/InstanceInfoServiceImpl.java | 32 +- .../InstanceInfoReportEventPublisher.java | 42 +++ ...stractShenyuClientRegisterServiceImpl.java | 23 ++ .../ShenyuClientURIExecutorSubscriber.java | 2 + .../register/common/dto/URIRegisterDTO.java | 114 +++++-- 12 files changed, 484 insertions(+), 313 deletions(-) delete mode 100644 shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceInfoDTO.java create mode 100644 shenyu-admin/src/main/java/org/apache/shenyu/admin/model/event/instance/InstanceInfoReportEvent.java create mode 100644 shenyu-admin/src/main/java/org/apache/shenyu/admin/service/publish/InstanceInfoReportEventPublisher.java diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/ShenyuAdminConfiguration.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/ShenyuAdminConfiguration.java index f3b9a8eb4c33..f4e568a7e693 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/ShenyuAdminConfiguration.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/ShenyuAdminConfiguration.java @@ -19,6 +19,8 @@ import org.apache.shenyu.admin.service.converter.SelectorHandleConverter; import org.apache.shenyu.admin.service.converter.SelectorHandleConverterFactor; +import org.apache.shenyu.admin.service.publish.InstanceInfoReportEventPublisher; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; @@ -62,4 +64,9 @@ public LocaleResolver localeResolver() { localeResolver.setSupportedLocales(Stream.of(Locale.US, Locale.SIMPLIFIED_CHINESE).collect(Collectors.toList())); return localeResolver; } + + @Bean + public InstanceInfoReportEventPublisher instanceInfoReportEventPublisher(final ApplicationEventPublisher publisher) { + return new InstanceInfoReportEventPublisher(publisher); + } } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java index 7edc377766e0..9e0a908e1814 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java @@ -17,6 +17,7 @@ package org.apache.shenyu.admin.controller; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import org.apache.shenyu.admin.aspect.annotation.RestApi; import org.apache.shenyu.admin.model.dto.InstanceBeatInfoDTO; @@ -34,6 +35,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; /** @@ -97,11 +99,11 @@ public ShenyuAdminResult detailInstanceInfo(@PathVariable("id") final String id) /** * receive beat. * - * @param id instance id. + * @param instanceBeatInfoDTO instanceBeatInfoDTO. * @return {@linkplain ShenyuAdminResult} */ @PostMapping("/beat") - public ShenyuAdminResult beat(@PathVariable("id") final InstanceBeatInfoDTO instanceBeatInfoDTO) { + public ShenyuAdminResult beat(@Valid @RequestBody final InstanceBeatInfoDTO instanceBeatInfoDTO) { //todo:admin集群模式下,请求转发给master节点 instanceCheckService.handleBeatInfo(instanceBeatInfoDTO); return ShenyuAdminResult.success(ShenyuResultMessage.DETAIL_SUCCESS, null); diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceInfoDTO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceInfoDTO.java deleted file mode 100644 index e3dc98a42966..000000000000 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceInfoDTO.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.shenyu.admin.model.dto; - -import jakarta.validation.constraints.NotBlank; -import org.apache.shenyu.admin.mapper.NamespaceMapper; -import org.apache.shenyu.admin.validation.annotation.Existed; - -import java.io.Serializable; -import java.util.Objects; - -/** - * InstanceInfoDTO. - */ -public class InstanceInfoDTO implements Serializable { - - private static final long serialVersionUID = 3644412439977354321L; - - /** - * instance id. - */ - private String instanceId; - - /** - * instance ip. - */ - private String instanceIp; - - /** - * instance port. - */ - private String instancePort; - - /** - * instance type. - */ - private String instanceType; - - /** - * instance info. - */ - private String instanceInfo; - - /** - * instance state. - */ - private Integer instanceState; - - /** - * namespaceId. - */ - @NotBlank - @Existed(message = "namespaceId is not existed", provider = NamespaceMapper.class) - private String namespaceId; - - /** - * get getInstanceId. - * - * @return InstanceId - */ - public String getInstanceId() { - return instanceId; - } - - /** - * set instanceId. - * - * @param instanceId instanceId - */ - public void setInstanceId(final String instanceId) { - this.instanceId = instanceId; - } - - /** - * get instanceIp. - * - * @return instanceIp - */ - public String getInstanceIp() { - return instanceIp; - } - - /** - * set instanceIp. - * - * @param instanceIp instanceIp - */ - public void setInstanceIp(final String instanceIp) { - this.instanceIp = instanceIp; - } - - /** - * get instancePort. - * - * @return instancePort - */ - public String getInstancePort() { - return instancePort; - } - - /** - * set instancePort. - * - * @param instancePort instancePort - */ - public void setInstancePort(final String instancePort) { - this.instancePort = instancePort; - } - - /** - * get instanceType. - * - * @return instanceType - */ - public String getInstanceType() { - return instanceType; - } - - /** - * set instanceType. - * - * @param instanceType instanceType - */ - public void setInstanceType(final String instanceType) { - this.instanceType = instanceType; - } - - /** - * get instanceInfo. - * - * @return instanceInfo - */ - public String getInstanceInfo() { - return instanceInfo; - } - - /** - * set instanceInfo. - * - * @param instanceInfo instanceInfo - */ - public void setInstanceInfo(final String instanceInfo) { - this.instanceInfo = instanceInfo; - } - - /** - * get instanceState. - * - * @return instanceState - */ - public Integer getInstanceState() { - return instanceState; - } - - /** - * set instanceState. - * - * @param instanceState instanceState - */ - public void setInstanceState(final Integer instanceState) { - this.instanceState = instanceState; - } - - /** - * get namespaceId. - * - * @return namespaceId - */ - public String getNamespaceId() { - return namespaceId; - } - - /** - * set namespaceId. - * - * @param namespaceId namespaceId - */ - public void setNamespaceId(final String namespaceId) { - this.namespaceId = namespaceId; - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (Objects.isNull(o) || getClass() != o.getClass()) { - return false; - } - - InstanceInfoDTO that = (InstanceInfoDTO) o; - return Objects.equals(instanceIp, that.instanceIp) - && Objects.equals(instanceType, that.instanceType) - && Objects.equals(instanceInfo, that.instanceInfo) - && Objects.equals(namespaceId, that.namespaceId); - } - - @Override - public int hashCode() { - return Objects.hash(instanceIp, instanceType, instanceInfo, namespaceId); - } -} diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java index 8f9986c81622..48bc421c9650 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java @@ -17,7 +17,6 @@ package org.apache.shenyu.admin.model.entity; -import org.apache.shenyu.admin.model.dto.InstanceInfoDTO; import org.apache.shenyu.common.utils.UUIDUtils; import java.sql.Timestamp; @@ -101,27 +100,7 @@ public InstanceInfoDO(final String id, final Timestamp dateCreated, final Timest this.instanceInfo = instanceInfo; this.namespaceId = namespaceId; } - - /** - * build InstanceInfoDO. - * - * @param instanceInfoDTO instanceInfoDTO - * @return InstanceInfoDO - */ - public static InstanceInfoDO buildInstanceInfoDO(final InstanceInfoDTO instanceInfoDTO) { - Timestamp currentTime = new Timestamp(System.currentTimeMillis()); - return InstanceInfoDO.builder() - .id(UUIDUtils.getInstance().generateShortUuid()) - .instanceIp(instanceInfoDTO.getInstanceIp()) - .instancePort(instanceInfoDTO.getInstancePort()) - .instanceType(instanceInfoDTO.getInstanceType()) - .instanceInfo(instanceInfoDTO.getInstanceInfo()) - .instanceState(instanceInfoDTO.getInstanceState()) - .namespaceId(instanceInfoDTO.getNamespaceId()) - .dateCreated(currentTime) - .dateUpdated(currentTime) - .build(); - } + /** * get instanceIp. diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/event/instance/InstanceInfoReportEvent.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/event/instance/InstanceInfoReportEvent.java new file mode 100644 index 000000000000..82f14b1a6b36 --- /dev/null +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/event/instance/InstanceInfoReportEvent.java @@ -0,0 +1,301 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shenyu.admin.model.event.instance; + +/** + * InstanceInfoReportDTO. + */ +public class InstanceInfoReportEvent { + + /** + * instance ip. + */ + private String instanceIp; + + /** + * instance port. + */ + private String instancePort; + + /** + * instance type. + */ + private String instanceType; + + /** + * instance info. + */ + private String instanceInfo; + + /** + * instance state. + */ + private Integer instanceState; + + /** + * namespace id. + */ + private String namespaceId; + + public InstanceInfoReportEvent(final String instanceIp, final String instancePort, final String instanceType, final String instanceInfo, final String namespaceId) { + this.instanceIp = instanceIp; + this.instancePort = instancePort; + this.instanceType = instanceType; + this.instanceInfo = instanceInfo; + this.namespaceId = namespaceId; + } + + private InstanceInfoReportEvent(final Builder builder) { + this.instanceIp = builder.instanceIp; + this.instancePort = builder.instancePort; + this.instanceType = builder.instanceType; + this.instanceInfo = builder.instanceInfo; + this.instanceState = builder.instanceSate; + this.namespaceId = builder.namespaceId; + } + + /** + * builder method. + * + * @return builder object. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * get instance ip. + * + * @return instance ip + */ + public String getInstanceIp() { + return instanceIp; + } + + /** + * set instance ip. + * + * @param instanceIp instance ip + */ + public void setInstanceIp(final String instanceIp) { + this.instanceIp = instanceIp; + } + + /** + * get instance port. + * + * @return instance port + */ + public String getInstancePort() { + return instancePort; + } + + /** + * set instance port. + * + * @param instancePort instance port + */ + public void setInstancePort(final String instancePort) { + this.instancePort = instancePort; + } + + /** + * get instance type. + * + * @return instance type + */ + public String getInstanceType() { + return instanceType; + } + + /** + * set instance type. + * + * @param instanceType instance type + */ + public void setInstanceType(final String instanceType) { + this.instanceType = instanceType; + } + + /** + * get instance info. + * + * @return instance info + */ + public String getInstanceInfo() { + return instanceInfo; + } + + /** + * set instance info. + * + * @param instanceInfo instance info + */ + public void setInstanceInfo(final String instanceInfo) { + this.instanceInfo = instanceInfo; + } + + /** + * get instanceState. + * + * @return instanceState + */ + public Integer getInstanceState() { + return instanceState; + } + + /** + * set instanceState. + * + * @param instanceState instanceState + */ + public void setInstanceState(final Integer instanceState) { + this.instanceState = instanceState; + } + + /** + * get namespace id. + * + * @return namespace id + */ + public String getNamespaceId() { + return namespaceId; + } + + /** + * set namespace id. + * + * @param namespaceId namespace id + */ + public void setNamespaceId(final String namespaceId) { + this.namespaceId = namespaceId; + } + + + public static final class Builder { + + /** + * instance ip. + */ + private String instanceIp; + + /** + * instance port. + */ + private String instancePort; + + /** + * instance type. + */ + private String instanceType; + + /** + * instance info. + */ + private String instanceInfo; + + /** + * instance state. + */ + private Integer instanceSate; + + /** + * namespace id. + */ + private String namespaceId; + + private Builder() { + } + + /** + * instance type. + * + * @param instanceType instance type + * @return InstanceInfoRegisterDTO.Builder + */ + public Builder instanceType(final String instanceType) { + this.instanceType = instanceType; + return this; + } + + /** + * instance info. + * + * @param instanceInfo instance info + * @return InstanceInfoRegisterDTO.Builder + */ + public Builder instanceInfo(final String instanceInfo) { + this.instanceInfo = instanceInfo; + return this; + } + + /** + * instance ip. + * + * @param instanceIp instance ip + * @return InstanceInfoRegisterDTO.Builder + */ + public Builder instanceIp(final String instanceIp) { + this.instanceIp = instanceIp; + return this; + } + + /** + * instance port. + * + * @param instancePort instance port + * @return InstanceInfoRegisterDTO.Builder + */ + public Builder instancePort(final String instancePort) { + this.instancePort = instancePort; + return this; + } + + /** + * instance state. + * + * @param instanceState instance state + * @return InstanceInfoRegisterDTO.Builder + */ + public Builder instanceState(final Integer instanceState) { + this.instanceSate = instanceState; + return this; + } + + /** + * namespace id. + * + * @param namespaceId namespace id + * @return InstanceInfoRegisterDTO.Builder + */ + public Builder namespaceId(final String namespaceId) { + this.namespaceId = namespaceId; + return this; + } + + /** + * build. + * + * @return InstanceInfoRegisterDTO instance info register dto + */ + public InstanceInfoReportEvent build() { + return new InstanceInfoReportEvent(this); + } + + } +} diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/InstanceInfoService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/InstanceInfoService.java index 56a51c9a23c2..54102d822e7c 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/InstanceInfoService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/InstanceInfoService.java @@ -17,7 +17,6 @@ package org.apache.shenyu.admin.service; -import org.apache.shenyu.admin.model.dto.InstanceInfoDTO; import org.apache.shenyu.admin.model.page.CommonPager; import org.apache.shenyu.admin.model.query.InstanceQuery; import org.apache.shenyu.admin.model.query.InstanceQueryCondition; @@ -26,13 +25,6 @@ import java.util.List; public interface InstanceInfoService extends PageService { - - /** - * Creates or updates an instance information record. - * - * @param instanceInfoDTO the instance information data transfer object - */ - void createOrUpdate(InstanceInfoDTO instanceInfoDTO); /** * Creates or updates an instance information record. diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java index 40fdb0019979..cea4a6b5774f 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java @@ -3,11 +3,13 @@ import com.google.common.collect.Lists; import jakarta.annotation.PreDestroy; import org.apache.shenyu.admin.model.dto.InstanceBeatInfoDTO; +import org.apache.shenyu.admin.model.event.instance.InstanceInfoReportEvent; import org.apache.shenyu.admin.model.vo.InstanceInfoVO; import org.apache.shenyu.admin.service.InstanceInfoService; import org.apache.shenyu.common.concurrent.ShenyuThreadFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import java.util.List; @@ -136,4 +138,24 @@ public void close() { syncDB(); executor.shutdown(); } + /** + * listen {@link InstanceInfoReportEvent} instance info report event. + * + * @param event event + */ + @EventListener(InstanceInfoReportEvent.class) + public void onInstanceInfoReport(final InstanceInfoReportEvent event) { + InstanceBeatInfoDTO InstanceBeatInfoDTO = buildInstanceInfoDTO(event); + handleBeatInfo(InstanceBeatInfoDTO); + } + + private InstanceBeatInfoDTO buildInstanceInfoDTO(final InstanceInfoReportEvent instanceInfoRegisterDTO) { + InstanceBeatInfoDTO instanceInfoDTO = new InstanceBeatInfoDTO(); + instanceInfoDTO.setInstanceIp(instanceInfoRegisterDTO.getInstanceIp()); + instanceInfoDTO.setInstancePort(instanceInfoRegisterDTO.getInstancePort()); + instanceInfoDTO.setInstanceType(instanceInfoRegisterDTO.getInstanceType()); + instanceInfoDTO.setInstanceInfo(instanceInfoRegisterDTO.getInstanceInfo()); + instanceInfoDTO.setNamespaceId(instanceInfoRegisterDTO.getNamespaceId()); + return instanceInfoDTO; + } } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java index 79aa7f24ff3c..1fe5b1a40d1e 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java @@ -18,8 +18,9 @@ package org.apache.shenyu.admin.service.impl; import org.apache.shenyu.admin.mapper.InstanceInfoMapper; -import org.apache.shenyu.admin.model.dto.InstanceInfoDTO; +import org.apache.shenyu.admin.model.dto.InstanceBeatInfoDTO; import org.apache.shenyu.admin.model.entity.InstanceInfoDO; +import org.apache.shenyu.admin.model.event.instance.InstanceInfoReportEvent; import org.apache.shenyu.admin.model.page.CommonPager; import org.apache.shenyu.admin.model.page.PageResultUtils; import org.apache.shenyu.admin.model.query.InstanceQuery; @@ -28,6 +29,7 @@ import org.apache.shenyu.common.utils.GsonUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import java.sql.Timestamp; @@ -49,34 +51,6 @@ public InstanceInfoServiceImpl(final InstanceInfoMapper instanceInfoMapper) { this.instanceInfoMapper = instanceInfoMapper; } - @Override - public void createOrUpdate(final InstanceInfoDTO instanceInfoDTO) { - InstanceQuery instanceQuery = new InstanceQuery(); - instanceQuery.setInstanceIp(instanceInfoDTO.getInstanceIp()); - instanceQuery.setInstancePort(instanceInfoDTO.getInstancePort()); - instanceQuery.setInstanceType(instanceInfoDTO.getInstanceType()); - instanceQuery.setNamespaceId(instanceInfoDTO.getNamespaceId()); - InstanceInfoDO infoDO = instanceInfoMapper.selectOneByQuery(instanceQuery); - if (Objects.isNull(infoDO)) { - LOG.info("Register new instance info: {}", GsonUtils.getInstance().toJson(instanceInfoDTO)); - InstanceInfoDO instanceInfoDO = InstanceInfoDO.buildInstanceInfoDO(instanceInfoDTO); - try { - instanceInfoMapper.insert(instanceInfoDO); - } catch (Exception e) { - LOG.error("Failed to register instance info", e); - } - return; - } - LOG.info("Update instance info: {}", GsonUtils.getInstance().toJson(instanceInfoDTO)); - infoDO.setInstanceIp(instanceInfoDTO.getInstanceIp()); - infoDO.setInstanceType(instanceInfoDTO.getInstanceType()); - infoDO.setInstanceInfo(instanceInfoDTO.getInstanceInfo()); - infoDO.setNamespaceId(instanceInfoDTO.getNamespaceId()); - infoDO.setDateUpdated(Timestamp.from(Instant.now())); - infoDO.setInstanceState(instanceInfoDTO.getInstanceState()); - instanceInfoMapper.updateById(infoDO); - } - @Override public void createOrUpdate(InstanceInfoVO instanceInfoVO) { InstanceQuery instanceQuery = new InstanceQuery(); diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/publish/InstanceInfoReportEventPublisher.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/publish/InstanceInfoReportEventPublisher.java new file mode 100644 index 000000000000..f6648b5eb1e1 --- /dev/null +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/publish/InstanceInfoReportEventPublisher.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shenyu.admin.service.publish; + +import org.apache.shenyu.admin.model.event.instance.InstanceInfoReportEvent; +import org.springframework.context.ApplicationEventPublisher; + +/** + * InstanceInfoReportEventPublisher. + */ +public class InstanceInfoReportEventPublisher { + + private final ApplicationEventPublisher publisher; + + public InstanceInfoReportEventPublisher(final ApplicationEventPublisher publisher) { + this.publisher = publisher; + } + + /** + * event. + * + * @param event event. + */ + public void publish(final InstanceInfoReportEvent event) { + publisher.publishEvent(event); + } +} diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImpl.java index 429ec642b5b3..0f6f819448d9 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImpl.java @@ -28,6 +28,7 @@ import org.apache.shenyu.admin.model.dto.RuleDTO; import org.apache.shenyu.admin.model.entity.PluginDO; import org.apache.shenyu.admin.model.entity.SelectorDO; +import org.apache.shenyu.admin.model.event.instance.InstanceInfoReportEvent; import org.apache.shenyu.admin.model.vo.NamespacePluginVO; import org.apache.shenyu.admin.service.DiscoveryService; import org.apache.shenyu.admin.service.DiscoveryUpstreamService; @@ -36,9 +37,11 @@ import org.apache.shenyu.admin.service.SelectorService; import org.apache.shenyu.admin.service.impl.UpstreamCheckService; import org.apache.shenyu.admin.service.manager.RegisterApiDocService; +import org.apache.shenyu.admin.service.publish.InstanceInfoReportEventPublisher; import org.apache.shenyu.admin.utils.CommonUpstreamUtils; import org.apache.shenyu.admin.utils.ShenyuResultMessage; import org.apache.shenyu.common.constant.AdminConstants; +import org.apache.shenyu.common.constant.InstanceTypeConstants; import org.apache.shenyu.common.dto.DiscoverySyncData; import org.apache.shenyu.common.dto.DiscoveryUpstreamData; import org.apache.shenyu.common.dto.SelectorData; @@ -111,6 +114,9 @@ public abstract class AbstractShenyuClientRegisterServiceImpl extends FallbackSh @Resource private NamespacePluginRelMapper namespacePluginRelMapper; + @Resource + private InstanceInfoReportEventPublisher publisher; + /** * Selector handler string. * @@ -248,9 +254,26 @@ public String doHeartbeat(final String selectorName, final List uriRegisterDTO.getPort(), uriRegisterDTO.getProtocol(), uriRegisterDTO.getNamespaceId()); + + try { + // publish instance info event + publisher.publish( + new InstanceInfoReportEvent( + uriRegisterDTO.getHost(), + String.valueOf(uriRegisterDTO.getPort()), + InstanceTypeConstants.CLIENT_INSTANCE_TYPE, + uriRegisterDTO.getInstanceInfo(), + uriRegisterDTO.getNamespaceId() + ) + ); + } catch (Exception e) { + LOG.error("publish instance info error", e); + } + LOG.info("change alive selectorId={}|url={}", selectorId, discoveryUpstreamDTO.getUrl()); discoveryUpstreamService.changeStatusBySelectorIdAndUrl(selectorId, discoveryUpstreamDTO.getUrl(), Boolean.TRUE); }); + DiscoverySyncData discoverySyncData = fetch(selectorId, selectorDO.getName(), pluginName, namespaceId); eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.DISCOVER_UPSTREAM, DataEventTypeEnum.REFRESH, Collections.singletonList(discoverySyncData))); diff --git a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java index 6fa228dc881d..c84b05a637d8 100644 --- a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java +++ b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java @@ -22,6 +22,7 @@ import org.apache.shenyu.client.core.shutdown.ShenyuClientShutdownHook; import org.apache.shenyu.client.core.shutdown.ShutdownHookManager; import org.apache.shenyu.common.concurrent.ShenyuThreadFactory; +import org.apache.shenyu.common.utils.SystemInfoUtils; import org.apache.shenyu.register.client.api.ShenyuClientRegisterRepository; import org.apache.shenyu.register.common.dto.URIRegisterDTO; import org.apache.shenyu.register.common.enums.EventType; @@ -116,6 +117,7 @@ public void executor(final Collection dataList) { } private void sendHeartbeat(final URIRegisterDTO uriRegisterDTO) { + uriRegisterDTO.setInstanceInfo(SystemInfoUtils.getSystemInfo()); shenyuClientRegisterRepository.sendHeartbeat(uriRegisterDTO); } } diff --git a/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/URIRegisterDTO.java b/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/URIRegisterDTO.java index 36b169029081..032c4102e2fd 100644 --- a/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/URIRegisterDTO.java +++ b/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/URIRegisterDTO.java @@ -27,7 +27,7 @@ * The type URI register dto. */ public class URIRegisterDTO implements DataTypeParent { - + private String protocol; private String appName; @@ -41,9 +41,14 @@ public class URIRegisterDTO implements DataTypeParent { private Integer port; private EventType eventType; - + private String namespaceId; - + + /** + * instance info. + */ + private String instanceInfo; + /** * Instantiates a new Uri register dto. * @@ -54,10 +59,12 @@ public class URIRegisterDTO implements DataTypeParent { * @param host the host * @param port the port * @param eventType the event type + * @param namespaceId the namespace id + * @param instanceInfo the instance info */ public URIRegisterDTO(final String protocol, final String appName, final String contextPath, final String rpcType, final String host, final Integer port, - final EventType eventType, final String namespaceId) { + final EventType eventType, final String namespaceId, final String instanceInfo) { this.protocol = protocol; this.appName = appName; this.contextPath = contextPath; @@ -66,8 +73,9 @@ public URIRegisterDTO(final String protocol, final String appName, final String this.port = port; this.eventType = eventType; this.namespaceId = namespaceId; + this.instanceInfo = instanceInfo; } - + /** * Instantiates a new Uri register dto. */ @@ -83,8 +91,9 @@ private URIRegisterDTO(final Builder builder) { port = builder.port; eventType = builder.eventType; namespaceId = builder.namespaceId; + instanceInfo = builder.instanceInfo; } - + /** * Trans form uri register dto. * @@ -99,7 +108,7 @@ public static URIRegisterDTO transForm(final MetaDataRegisterDTO metaDataRegiste .host(metaDataRegisterDTO.getHost()) .port(metaDataRegisterDTO.getPort()).build(); } - + /** * return builder. * @@ -118,7 +127,7 @@ public static Builder builder() { public DataType getType() { return DataType.URI; } - + /** * Gets protocol. * @@ -127,7 +136,7 @@ public DataType getType() { public String getProtocol() { return protocol; } - + /** * Sets protocol. * @@ -136,7 +145,7 @@ public String getProtocol() { public void setProtocol(final String protocol) { this.protocol = protocol; } - + /** * getAppName. * @@ -145,7 +154,7 @@ public void setProtocol(final String protocol) { public String getAppName() { return appName; } - + /** * setAppName. * @@ -154,7 +163,7 @@ public String getAppName() { public void setAppName(final String appName) { this.appName = appName; } - + /** * getContextPath. * @@ -163,7 +172,7 @@ public void setAppName(final String appName) { public String getContextPath() { return contextPath; } - + /** * setContextPath. * @@ -172,7 +181,7 @@ public String getContextPath() { public void setContextPath(final String contextPath) { this.contextPath = contextPath; } - + /** * getRpcType. * @@ -181,7 +190,7 @@ public void setContextPath(final String contextPath) { public String getRpcType() { return rpcType; } - + /** * setRpcType. * @@ -190,7 +199,7 @@ public String getRpcType() { public void setRpcType(final String rpcType) { this.rpcType = rpcType; } - + /** * getHost. * @@ -199,7 +208,7 @@ public void setRpcType(final String rpcType) { public String getHost() { return host; } - + /** * setHost. * @@ -208,7 +217,7 @@ public String getHost() { public void setHost(final String host) { this.host = host; } - + /** * getPort. * @@ -217,7 +226,7 @@ public void setHost(final String host) { public Integer getPort() { return port; } - + /** * setPort. * @@ -226,7 +235,7 @@ public Integer getPort() { public void setPort(final Integer port) { this.port = port; } - + /** * getEventType. * @@ -235,7 +244,7 @@ public void setPort(final Integer port) { public EventType getEventType() { return eventType; } - + /** * getNamespaceId. * @@ -244,7 +253,7 @@ public EventType getEventType() { public String getNamespaceId() { return namespaceId; } - + /** * setNamespaceId. * @@ -253,7 +262,25 @@ public String getNamespaceId() { public void setNamespaceId(final String namespaceId) { this.namespaceId = namespaceId; } - + + /** + * getInstanceInfo. + * + * @return String instance info + */ + public String getInstanceInfo() { + return instanceInfo; + } + + /** + * setInstanceInfo. + * + * @param instanceInfo instance info + */ + public void setInstanceInfo(final String instanceInfo) { + this.instanceInfo = instanceInfo; + } + /** * setEventType. * @@ -281,12 +308,14 @@ public boolean equals(final Object o) { && Objects.equals(getHost(), that.getHost()) && Objects.equals(getPort(), that.getPort()) && getEventType() == that.getEventType() - && Objects.equals(getNamespaceId(), that.getNamespaceId()); + && Objects.equals(getNamespaceId(), that.getNamespaceId()) + && Objects.equals(getInstanceInfo(), that.getInstanceInfo()); } @Override public int hashCode() { - return Objects.hash(getProtocol(), getAppName(), getContextPath(), getRpcType(), getHost(), getPort(), getEventType()); + return Objects.hash(getProtocol(), getAppName(), getContextPath(), getRpcType(), getHost(), + getPort(), getEventType(), getNamespaceId(), getInstanceInfo()); } @Override @@ -313,6 +342,8 @@ public String toString() { + eventType + ", namespaceId=" + namespaceId + + ", instanceInfo=" + + instanceInfo + '}'; } @@ -320,7 +351,7 @@ public String toString() { * The type Builder. */ public static final class Builder { - + private String protocol; private String appName; @@ -334,12 +365,14 @@ public static final class Builder { private Integer port; private EventType eventType; - + private String namespaceId; + private String instanceInfo; + private Builder() { } - + /** * protocol. * @@ -350,7 +383,7 @@ public Builder protocol(final String protocol) { this.protocol = protocol; return this; } - + /** * appName. * @@ -361,7 +394,7 @@ public Builder appName(final String appName) { this.appName = appName; return this; } - + /** * contextPath. * @@ -372,7 +405,7 @@ public Builder contextPath(final String contextPath) { this.contextPath = contextPath; return this; } - + /** * rpcType. * @@ -383,7 +416,7 @@ public Builder rpcType(final String rpcType) { this.rpcType = rpcType; return this; } - + /** * host. * @@ -394,7 +427,7 @@ public Builder host(final String host) { this.host = host; return this; } - + /** * port. * @@ -405,7 +438,7 @@ public Builder port(final Integer port) { this.port = port; return this; } - + /** * eventType. * @@ -416,7 +449,7 @@ public Builder eventType(final EventType eventType) { this.eventType = eventType; return this; } - + /** * namespace. * @@ -428,6 +461,17 @@ public Builder namespaceId(final String namespaceId) { return this; } + /** + * instanceInfo. + * + * @param instanceInfo instance info + * @return Builder builder + */ + public Builder instanceInfo(final String instanceInfo) { + this.instanceInfo = instanceInfo; + return this; + } + /** * build. * From 018e04b9c1a179d1f19b45aa23e4a9daeb0765bb Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Sat, 12 Jul 2025 17:08:53 +0800 Subject: [PATCH 04/17] client finish --- .../URIRegisterExecutorSubscriber.java | 2 +- .../admin/model/entity/InstanceInfoDO.java | 22 +++++++++++++++++++ .../service/impl/InstanceCheckService.java | 15 ++++++++----- .../service/impl/InstanceInfoServiceImpl.java | 8 ++++++- .../ShenyuClientURIExecutorSubscriber.java | 2 +- 5 files changed, 41 insertions(+), 8 deletions(-) diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/disruptor/subscriber/URIRegisterExecutorSubscriber.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/disruptor/subscriber/URIRegisterExecutorSubscriber.java index 5ff30e5ebdcc..254e268fa0cf 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/disruptor/subscriber/URIRegisterExecutorSubscriber.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/disruptor/subscriber/URIRegisterExecutorSubscriber.java @@ -95,7 +95,7 @@ public void executor(final Collection dataList) { heartbeat.stream().map(URIRegisterDTO::getNamespaceId) .filter(StringUtils::isNotBlank) .findFirst() - .ifPresent(namespaceId -> service.heartbeat(selectorName, register, namespaceId)); + .ifPresent(namespaceId -> service.heartbeat(selectorName, heartbeat, namespaceId)); } if (CollectionUtils.isNotEmpty(offline)) { offline.stream().map(URIRegisterDTO::getNamespaceId) diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java index 48bc421c9650..9d19ca10800d 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java @@ -17,6 +17,7 @@ package org.apache.shenyu.admin.model.entity; +import org.apache.shenyu.admin.model.vo.InstanceInfoVO; import org.apache.shenyu.common.utils.UUIDUtils; import java.sql.Timestamp; @@ -261,6 +262,27 @@ public boolean equals(final Object o) { public int hashCode() { return Objects.hash(super.hashCode(), instanceIp, instancePort, instanceType, instanceInfo, instanceState, namespaceId); } + + /** + * build InstanceInfoDO. + * + * @param instanceInfoVO instanceInfoVO + * @return InstanceInfoDO + */ + public static InstanceInfoDO buildInstanceInfoDO(final InstanceInfoVO instanceInfoVO) { + Timestamp currentTime = new Timestamp(System.currentTimeMillis()); + return InstanceInfoDO.builder() + .id(UUIDUtils.getInstance().generateShortUuid()) + .instanceIp(instanceInfoVO.getInstanceIp()) + .instancePort(instanceInfoVO.getInstancePort()) + .instanceType(instanceInfoVO.getInstanceType()) + .instanceInfo(instanceInfoVO.getInstanceInfo()) + .instanceState(instanceInfoVO.getInstanceState()) + .namespaceId(instanceInfoVO.getNamespaceId()) + .dateCreated(currentTime) + .dateUpdated(currentTime) + .build(); + } public static final class InstanceInfoDOBuilder { diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java index cea4a6b5774f..b7807254ea3f 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java @@ -43,10 +43,10 @@ public class InstanceCheckService { public InstanceCheckService(InstanceInfoService instanceInfoService) { - this.scheduledTime = 500; + this.scheduledTime = 10; this.instanceHealthBeatInfo = new ConcurrentHashMap<>(); - this.instanceHeartBeatTimeOut = 500; - this.deleteTimeout = 500; + this.instanceHeartBeatTimeOut = 1000 * 20; + this.deleteTimeout = 1000 * 60; this.instanceInfoService = instanceInfoService; } @@ -56,7 +56,8 @@ public InstanceCheckService(InstanceInfoService instanceInfoService) { public void setup() { this.fetchInstanceData(); executor = new ScheduledThreadPoolExecutor(1, ShenyuThreadFactory.create("scheduled-instance-task", false)); - scheduledFuture = executor.scheduleWithFixedDelay(this::scheduled, 10, scheduledTime, TimeUnit.SECONDS); + executor.scheduleWithFixedDelay(this::scheduled, 30, scheduledTime, TimeUnit.SECONDS); + executor.scheduleWithFixedDelay(this::syncDB, 40, scheduledTime, TimeUnit.SECONDS); } /** @@ -84,7 +85,7 @@ public InstanceInfoVO getInstanceHealthBeatInfo(InstanceBeatInfoDTO instanceBeat public void handleBeatInfo(InstanceBeatInfoDTO instanceBeatInfoDTO){ String instanceKey = getInstanceKey(instanceBeatInfoDTO); - if (instanceHealthBeatInfo.contains(instanceKey)){ + if (instanceHealthBeatInfo.containsKey(instanceKey)){ InstanceInfoVO instanceInfoVO = instanceHealthBeatInfo.get(instanceKey); instanceInfoVO.setLastHeartBeatTime(System.currentTimeMillis()); }else { @@ -96,6 +97,7 @@ public void handleBeatInfo(InstanceBeatInfoDTO instanceBeatInfoDTO){ instanceInfoVO.setLastHeartBeatTime(System.currentTimeMillis()); instanceInfoVO.setInstancePort(instanceBeatInfoDTO.getInstancePort()); instanceInfoVO.setNamespaceId(instanceBeatInfoDTO.getNamespaceId()); + instanceInfoVO.setLastHeartBeatTime(System.currentTimeMillis()); instanceHealthBeatInfo.put(instanceKey,instanceInfoVO); } } @@ -115,6 +117,9 @@ private void doCheck() { LOG.info("[instanceHealthInfo]namespace:{},type:{},Ip:{},Port:{} offline!", instance.getNamespaceId(), instance.getInstanceType(), instance.getInstanceIp(), instance.getInstancePort()); instance.setInstanceState(2); } + }else{ + LOG.info("[instanceHealthInfo]namespace:{},type:{},Ip:{},Port:{} online!", instance.getNamespaceId(), instance.getInstanceType(), instance.getInstanceIp(), instance.getInstancePort()); + instance.setInstanceState(1); } if (System.currentTimeMillis() - instance.getLastHeartBeatTime() > deleteTimeout) { if (2 == instance.getInstanceState()) { diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java index 1fe5b1a40d1e..1793d332dce1 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java @@ -60,7 +60,13 @@ public void createOrUpdate(InstanceInfoVO instanceInfoVO) { instanceQuery.setNamespaceId(instanceInfoVO.getNamespaceId()); InstanceInfoDO infoDO = instanceInfoMapper.selectOneByQuery(instanceQuery); if (Objects.isNull(infoDO)) { - LOG.info("update instance info fail: {}", GsonUtils.getInstance().toJson(instanceInfoVO)); + LOG.info("Register new instance info: {}", GsonUtils.getInstance().toJson(instanceQuery)); + InstanceInfoDO instanceInfoDO = InstanceInfoDO.buildInstanceInfoDO(instanceInfoVO); + try { + instanceInfoMapper.insert(instanceInfoDO); + } catch (Exception e) { + LOG.error("Failed to register instance info", e); + } return; } LOG.info("Update instance info: {}", GsonUtils.getInstance().toJson(instanceInfoVO)); diff --git a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java index c84b05a637d8..cdfdbce3ea97 100644 --- a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java +++ b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java @@ -64,7 +64,7 @@ public ShenyuClientURIExecutorSubscriber(final ShenyuClientRegisterRepository sh ThreadFactory requestFactory = ShenyuThreadFactory.create("heartbeat-reporter", true); executor = new ScheduledThreadPoolExecutor(1, requestFactory); - executor.scheduleAtFixedRate(() -> URIS.forEach(this::sendHeartbeat), 30, 30, TimeUnit.SECONDS); + executor.scheduleAtFixedRate(() -> URIS.forEach(this::sendHeartbeat), 30, 10, TimeUnit.SECONDS); } @Override From 4a26e8c94d6a6be0d07b9bbb761e4b1e4d6defbb Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Sun, 13 Jul 2025 23:26:51 +0800 Subject: [PATCH 05/17] 1 --- .../web/listener/HeartbeatReporter.java | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 shenyu-web/src/main/java/org/apache/shenyu/web/listener/HeartbeatReporter.java diff --git a/shenyu-web/src/main/java/org/apache/shenyu/web/listener/HeartbeatReporter.java b/shenyu-web/src/main/java/org/apache/shenyu/web/listener/HeartbeatReporter.java new file mode 100644 index 000000000000..743c90d80a67 --- /dev/null +++ b/shenyu-web/src/main/java/org/apache/shenyu/web/listener/HeartbeatReporter.java @@ -0,0 +1,124 @@ +package org.apache.shenyu.web.listener; + +import com.google.common.collect.Lists; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.netty.handler.codec.Headers; +import org.apache.shenyu.common.concurrent.ShenyuThreadFactory; +import org.apache.shenyu.common.constant.Constants; +import org.apache.shenyu.common.constant.InstanceTypeConstants; +import org.apache.shenyu.common.dto.ConfigData; +import org.apache.shenyu.common.enums.ConfigGroupEnum; +import org.apache.shenyu.common.exception.ShenyuException; +import org.apache.shenyu.common.utils.GsonUtils; +import org.apache.shenyu.common.utils.IpUtils; +import org.apache.shenyu.common.utils.SystemInfoUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.context.event.EventListener; +import org.springframework.util.Assert; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.util.UriComponentsBuilder; + +import java.io.IOException; +import java.util.Collections; +import java.util.Objects; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class HeartbeatReporter implements ApplicationListener { + + private static final Logger LOG = LoggerFactory.getLogger(HeartbeatReporter.class); + + private ScheduledThreadPoolExecutor executor; + + + public HeartbeatReporter(ScheduledThreadPoolExecutor executor) { + executor = new ScheduledThreadPoolExecutor(1, ShenyuThreadFactory.create("scheduled-instance-task", false)); + } + + @Override + public void onApplicationEvent(ServletWebServerInitializedEvent event) { + + int port = event.getWebServer().getPort(); + LOG.info("Web server initialized on port {}, starting heartbeat reporter", port); + +// // 初始化本地IP +// localIp = getLocalIp(); +// log.info("Detected local IP: {}", localIp); + + // 启动心跳任务 +// executor.scheduleAtFixedRate(this::report, +// 0, +// 5, +// TimeUnit.SECONDS +// ); + } +// /** +// * Get the host. +// * +// * @return the host +// */ +// public String getHost() { +// return IpUtils.isCompleteHost(this.host) ? this.host +// : IpUtils.getHost(this.host); +// } +// private void report() { +// MultiValueMap params = new LinkedMultiValueMap<>(8); +// params.put("namespaceId", Collections.singletonList("1")); +// LOG.debug("listener params: [{}]", params); +// Headers headers = new Headers.Builder() +// .add(Constants.X_ACCESS_TOKEN, accessTokenManager.getAccessToken()) +// .add("Content-Type", "application/x-www-form-urlencoded") +// .add("X-Real-PORT", port + "") +// .add(InstanceTypeConstants.BOOTSTRAP_INSTANCE_INFO, SystemInfoUtils.getSystemInfo()) +// .build(); +// String listenerUrl = server + Constants.SHENYU_ADMIN_PATH_CONFIGS_LISTENER; +// String uri = UriComponentsBuilder.fromHttpUrl(listenerUrl).queryParams(params).build(true).toUriString(); +// Request request = new Request.Builder() +// .url(uri) +// .headers(headers) +// .post(RequestBody.create("", null)) +// .build(); +// +// JsonArray groupJson; +// try (Response response = okHttpClient.newCall(request).execute()) { +// if (!response.isSuccessful()) { +// String message = String.format("listener configs fail, server:[%s], http status code[%s]", server, response.code()); +// throw new ShenyuException(message); +// } +// ResponseBody responseBody = response.body(); +// Assert.notNull(responseBody, "Resolve response body failed."); +// String json = responseBody.string(); +// LOG.info("listener result: [{}]", json); +// JsonObject responseFromServer = GsonUtils.getGson().fromJson(json, JsonObject.class); +// JsonElement element = responseFromServer.get("data"); +// if (element.isJsonNull()) { +// return; +// } +// groupJson = responseFromServer.getAsJsonArray("data"); +// } catch (IOException e) { +// String message = String.format("listener configs fail, server:[%s], %s", server, e.getMessage()); +// throw new ShenyuException(message, e); +// } +// } +// +// +// @EventListener(ContextClosedEvent.class) +// public void onShutdown() { +// scheduler.shutdown(); +// try { +// if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) { +// scheduler.shutdownNow(); +// } +// } catch (InterruptedException e) { +// Thread.currentThread().interrupt(); +// } +// log.info("Heartbeat reporter shutdown complete"); +// } +} \ No newline at end of file From dd31c836eaf405af3594758c86a099ea779bedc0 Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Thu, 17 Jul 2025 00:13:56 +0800 Subject: [PATCH 06/17] bootstrap finish --- .../admin/controller/InstanceController.java | 6 +- .../service/impl/InstanceCheckService.java | 4 +- .../service/impl/InstanceInfoServiceImpl.java | 3 - shenyu-bootstrap/pom.xml | 5 + .../src/main/resources/application.yml | 8 +- .../shenyu/common/constant/Constants.java | 5 + shenyu-register-center/pom.xml | 1 + .../shenyu-register-client-beat/pom.xml | 31 +++++ .../client/beat/HeartbeatListener.java | 64 +++++++++ .../api/ShenyuClientRegisterRepository.java | 9 ++ .../http/HttpClientRegisterRepository.java | 7 +- .../common}/dto/InstanceBeatInfoDTO.java | 2 +- .../shenyu-spring-boot-starter-client/pom.xml | 1 + .../pom.xml | 32 +++++ .../beat/HeartbeatListenerConfiguration.java | 26 ++++ .../main/resources/META-INF/spring.factories | 19 +++ ...ot.autoconfigure.AutoConfiguration.imports | 18 +++ .../web/listener/HeartbeatReporter.java | 124 ------------------ 18 files changed, 227 insertions(+), 138 deletions(-) create mode 100644 shenyu-register-center/shenyu-register-client-beat/pom.xml create mode 100644 shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java rename {shenyu-admin/src/main/java/org/apache/shenyu/admin/model => shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common}/dto/InstanceBeatInfoDTO.java (97%) create mode 100644 shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/pom.xml create mode 100644 shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListenerConfiguration.java create mode 100644 shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/resources/META-INF/spring.factories create mode 100644 shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 shenyu-web/src/main/java/org/apache/shenyu/web/listener/HeartbeatReporter.java diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java index 9e0a908e1814..2ff8dcd0f228 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java @@ -20,7 +20,7 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import org.apache.shenyu.admin.aspect.annotation.RestApi; -import org.apache.shenyu.admin.model.dto.InstanceBeatInfoDTO; +import org.apache.shenyu.register.common.dto.InstanceBeatInfoDTO; import org.apache.shenyu.admin.model.page.CommonPager; import org.apache.shenyu.admin.model.page.PageParameter; import org.apache.shenyu.admin.model.query.InstanceQuery; @@ -103,10 +103,10 @@ public ShenyuAdminResult detailInstanceInfo(@PathVariable("id") final String id) * @return {@linkplain ShenyuAdminResult} */ @PostMapping("/beat") - public ShenyuAdminResult beat(@Valid @RequestBody final InstanceBeatInfoDTO instanceBeatInfoDTO) { + public String beat(@Valid @RequestBody final InstanceBeatInfoDTO instanceBeatInfoDTO) { //todo:admin集群模式下,请求转发给master节点 instanceCheckService.handleBeatInfo(instanceBeatInfoDTO); - return ShenyuAdminResult.success(ShenyuResultMessage.DETAIL_SUCCESS, null); + return ShenyuResultMessage.SUCCESS; } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java index b7807254ea3f..9f4ac6ec90f8 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java @@ -1,8 +1,7 @@ package org.apache.shenyu.admin.service.impl; -import com.google.common.collect.Lists; import jakarta.annotation.PreDestroy; -import org.apache.shenyu.admin.model.dto.InstanceBeatInfoDTO; +import org.apache.shenyu.register.common.dto.InstanceBeatInfoDTO; import org.apache.shenyu.admin.model.event.instance.InstanceInfoReportEvent; import org.apache.shenyu.admin.model.vo.InstanceInfoVO; import org.apache.shenyu.admin.service.InstanceInfoService; @@ -13,7 +12,6 @@ import org.springframework.stereotype.Component; import java.util.List; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java index 1793d332dce1..c50a93111e03 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java @@ -18,9 +18,7 @@ package org.apache.shenyu.admin.service.impl; import org.apache.shenyu.admin.mapper.InstanceInfoMapper; -import org.apache.shenyu.admin.model.dto.InstanceBeatInfoDTO; import org.apache.shenyu.admin.model.entity.InstanceInfoDO; -import org.apache.shenyu.admin.model.event.instance.InstanceInfoReportEvent; import org.apache.shenyu.admin.model.page.CommonPager; import org.apache.shenyu.admin.model.page.PageResultUtils; import org.apache.shenyu.admin.model.query.InstanceQuery; @@ -29,7 +27,6 @@ import org.apache.shenyu.common.utils.GsonUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import java.sql.Timestamp; diff --git a/shenyu-bootstrap/pom.xml b/shenyu-bootstrap/pom.xml index c9443530eb45..04a1af1484d2 100644 --- a/shenyu-bootstrap/pom.xml +++ b/shenyu-bootstrap/pom.xml @@ -594,6 +594,11 @@ shenyu-spring-boot-starter-plugin-basic-auth ${project.version} + + org.apache.shenyu + shenyu-spring-boot-starter-client-beat + ${project.version} + diff --git a/shenyu-bootstrap/src/main/resources/application.yml b/shenyu-bootstrap/src/main/resources/application.yml index 3c596c3d0c98..e1da6a1a5b0d 100644 --- a/shenyu-bootstrap/src/main/resources/application.yml +++ b/shenyu-bootstrap/src/main/resources/application.yml @@ -194,10 +194,12 @@ shenyu: # workerCount: 8 # daemon: true register: - enabled: false - registerType: zookeeper #etcd #consul - serverLists: localhost:2181 #http://localhost:2379 #localhost:8848 + enable: true + registerType: http + serverLists: http://localhost:9095 props: + username: admin + password: 123456 cross: enabled: true allowedHeaders: diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java index 5bd671d81494..79837c240322 100644 --- a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java +++ b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java @@ -627,6 +627,11 @@ public interface Constants { * When register by http, the uri path. */ String URI_PATH = "/shenyu-client/register-uri"; + + /** + * When register by http, the uri path. + */ + String BEAT_URI_PATH = "/instance/beat"; /** * When register by http, the offline path. diff --git a/shenyu-register-center/pom.xml b/shenyu-register-center/pom.xml index 743f02449d96..75b89b328a2f 100644 --- a/shenyu-register-center/pom.xml +++ b/shenyu-register-center/pom.xml @@ -29,6 +29,7 @@ shenyu-register-common shenyu-register-client + shenyu-register-client-beat diff --git a/shenyu-register-center/shenyu-register-client-beat/pom.xml b/shenyu-register-center/shenyu-register-client-beat/pom.xml new file mode 100644 index 000000000000..6f18cfda2558 --- /dev/null +++ b/shenyu-register-center/shenyu-register-client-beat/pom.xml @@ -0,0 +1,31 @@ + + + + org.apache.shenyu + shenyu-register-center + 2.7.0.2-SNAPSHOT + + 4.0.0 + + shenyu-register-client-beat + + + 17 + 17 + UTF-8 + + + + org.apache.shenyu + shenyu-register-client-http + ${project.version} + + + org.springframework.boot + spring-boot-starter-web + provided + + + \ No newline at end of file diff --git a/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java b/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java new file mode 100644 index 000000000000..3a207457b568 --- /dev/null +++ b/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java @@ -0,0 +1,64 @@ +package org.apache.shenyu.register.client.beat; + +import org.apache.shenyu.common.concurrent.ShenyuThreadFactory; +import org.apache.shenyu.common.config.ShenyuConfig; +import org.apache.shenyu.common.constant.InstanceTypeConstants; +import org.apache.shenyu.common.utils.IpUtils; +import org.apache.shenyu.common.utils.SystemInfoUtils; +import org.apache.shenyu.register.client.api.ShenyuClientRegisterRepository; +import org.apache.shenyu.register.client.http.HttpClientRegisterRepository; +import org.apache.shenyu.register.common.dto.InstanceBeatInfoDTO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.context.event.EventListener; + +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class HeartbeatListener{ + + private static final Logger LOG = LoggerFactory.getLogger(HeartbeatListener.class); + + private ScheduledThreadPoolExecutor executor; + + private final ShenyuClientRegisterRepository httpClientRegisterRepository; + + private final ShenyuConfig shenyuConfig; + + public HeartbeatListener(final ShenyuClientRegisterRepository httpClientRegisterRepository, final ShenyuConfig shenyuConfig, final ServerProperties serverProperties) { + executor = new ScheduledThreadPoolExecutor(1, ShenyuThreadFactory.create("scheduled-instance-task", false)); + this.httpClientRegisterRepository = httpClientRegisterRepository; + this.shenyuConfig = shenyuConfig; + LOG.info("Web server initialized on port {}, starting heartbeat reporter", serverProperties.getPort()); + //启动心跳任务 + executor.scheduleAtFixedRate(() -> { + InstanceBeatInfoDTO instanceBeatInfoDTO = new InstanceBeatInfoDTO(); + instanceBeatInfoDTO.setInstancePort(serverProperties.getPort()+""); + instanceBeatInfoDTO.setInstanceIp(IpUtils.getHost()); + instanceBeatInfoDTO.setNamespaceId(shenyuConfig.getNamespace()); + instanceBeatInfoDTO.setInstanceInfo(SystemInfoUtils.getSystemInfo()); + instanceBeatInfoDTO.setInstanceType(InstanceTypeConstants.BOOTSTRAP_INSTANCE_INFO); + httpClientRegisterRepository.sendHeartbeat(instanceBeatInfoDTO); + }, + 0, + 5, + TimeUnit.SECONDS + ); + } + + @EventListener(ContextClosedEvent.class) + public void onShutdown() { + executor.shutdown(); + try { + if (!executor.awaitTermination(5, TimeUnit.SECONDS)) { + executor.shutdownNow(); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } +} \ No newline at end of file diff --git a/shenyu-register-center/shenyu-register-client/shenyu-register-client-api/src/main/java/org/apache/shenyu/register/client/api/ShenyuClientRegisterRepository.java b/shenyu-register-center/shenyu-register-client/shenyu-register-client-api/src/main/java/org/apache/shenyu/register/client/api/ShenyuClientRegisterRepository.java index 43eead031afb..e12963160d98 100644 --- a/shenyu-register-center/shenyu-register-client/shenyu-register-client-api/src/main/java/org/apache/shenyu/register/client/api/ShenyuClientRegisterRepository.java +++ b/shenyu-register-center/shenyu-register-client/shenyu-register-client-api/src/main/java/org/apache/shenyu/register/client/api/ShenyuClientRegisterRepository.java @@ -19,6 +19,7 @@ import org.apache.shenyu.register.common.config.ShenyuRegisterCenterConfig; import org.apache.shenyu.register.common.dto.ApiDocRegisterDTO; +import org.apache.shenyu.register.common.dto.InstanceBeatInfoDTO; import org.apache.shenyu.register.common.dto.MetaDataRegisterDTO; import org.apache.shenyu.register.common.dto.URIRegisterDTO; import org.apache.shenyu.spi.SPI; @@ -68,6 +69,14 @@ default void offline(URIRegisterDTO offlineDTO) { default void sendHeartbeat(URIRegisterDTO heartbeatDTO) { } + /** + * Send heartbeat. + * + * @param instanceBeatInfoDTO the instanceBeatInfo dto + */ + default void sendHeartbeat(InstanceBeatInfoDTO instanceBeatInfoDTO) { + } + /** * persistApiDoc. * @param apiDocRegisterDTO apiDocRegisterDTO diff --git a/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/main/java/org/apache/shenyu/register/client/http/HttpClientRegisterRepository.java b/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/main/java/org/apache/shenyu/register/client/http/HttpClientRegisterRepository.java index 17569fa9d301..b828baaed8e7 100644 --- a/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/main/java/org/apache/shenyu/register/client/http/HttpClientRegisterRepository.java +++ b/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/main/java/org/apache/shenyu/register/client/http/HttpClientRegisterRepository.java @@ -32,6 +32,7 @@ import org.apache.shenyu.register.common.config.ShenyuRegisterCenterConfig; import org.apache.shenyu.register.common.dto.ApiDocRegisterDTO; import org.apache.shenyu.register.common.dto.DiscoveryConfigRegisterDTO; +import org.apache.shenyu.register.common.dto.InstanceBeatInfoDTO; import org.apache.shenyu.register.common.dto.MetaDataRegisterDTO; import org.apache.shenyu.register.common.dto.URIRegisterDTO; import org.apache.shenyu.register.common.enums.EventType; @@ -138,7 +139,11 @@ public void sendHeartbeat(final URIRegisterDTO heartbeatDTO) { heartbeatDTO.setEventType(EventType.HEARTBEAT); doHeartbeat(heartbeatDTO, Constants.URI_PATH); } - + + @Override + public void sendHeartbeat(InstanceBeatInfoDTO instanceBeatInfoDTO) { + doHeartbeat(instanceBeatInfoDTO, Constants.BEAT_URI_PATH); + } /** * doPersistApiDoc. * diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceBeatInfoDTO.java b/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/InstanceBeatInfoDTO.java similarity index 97% rename from shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceBeatInfoDTO.java rename to shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/InstanceBeatInfoDTO.java index 6b68794c1267..89016396efcc 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceBeatInfoDTO.java +++ b/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/InstanceBeatInfoDTO.java @@ -1,4 +1,4 @@ -package org.apache.shenyu.admin.model.dto; +package org.apache.shenyu.register.common.dto; public class InstanceBeatInfoDTO { /** diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/pom.xml b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/pom.xml index f6002648986f..25fa4c6af94d 100644 --- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/pom.xml +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/pom.xml @@ -35,5 +35,6 @@ shenyu-spring-boot-starter-client-common shenyu-spring-boot-starter-client-motan shenyu-spring-boot-starter-client-spring-websocket + shenyu-spring-boot-starter-client-beat diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/pom.xml b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/pom.xml new file mode 100644 index 000000000000..ad9b6690e8d2 --- /dev/null +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/pom.xml @@ -0,0 +1,32 @@ + + + + org.apache.shenyu + shenyu-spring-boot-starter-client + 2.7.0.2-SNAPSHOT + + 4.0.0 + + shenyu-spring-boot-starter-client-beat + + + 17 + 17 + UTF-8 + + + + + org.apache.shenyu + shenyu-spring-boot-starter-client-common + ${project.version} + + + org.apache.shenyu + shenyu-register-client-beat + ${project.version} + + + \ No newline at end of file diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListenerConfiguration.java b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListenerConfiguration.java new file mode 100644 index 000000000000..005e432a1103 --- /dev/null +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListenerConfiguration.java @@ -0,0 +1,26 @@ +package org.apache.shenyu.register.client.beat; + +import org.apache.shenyu.common.config.ShenyuConfig; +import org.apache.shenyu.register.client.api.ShenyuClientRegisterRepository; +import org.apache.shenyu.register.client.http.HttpClientRegisterRepository; +import org.apache.shenyu.springboot.starter.client.common.config.ShenyuClientCommonBeanConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ImportAutoConfiguration(ShenyuClientCommonBeanConfiguration.class) +@ConditionalOnProperty(value = "shenyu.register.enabled", matchIfMissing = true, havingValue = "true") +public class HeartbeatListenerConfiguration { + + + @Bean + public HeartbeatListener heartbeatListener(final ShenyuClientRegisterRepository httpClientRegisterRepository, + final ShenyuConfig shenyuConfig, + final ServerProperties serverProperties) { + return new HeartbeatListener(httpClientRegisterRepository, shenyuConfig, serverProperties); + } + +} diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/resources/META-INF/spring.factories b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000000..23326a881f1f --- /dev/null +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/resources/META-INF/spring.factories @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.apache.shenyu.register.client.beat.HeartbeatListenerConfiguration diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000000..f79b9bac1e8d --- /dev/null +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +org.apache.shenyu.register.client.beat.HeartbeatListenerConfiguration diff --git a/shenyu-web/src/main/java/org/apache/shenyu/web/listener/HeartbeatReporter.java b/shenyu-web/src/main/java/org/apache/shenyu/web/listener/HeartbeatReporter.java deleted file mode 100644 index 743c90d80a67..000000000000 --- a/shenyu-web/src/main/java/org/apache/shenyu/web/listener/HeartbeatReporter.java +++ /dev/null @@ -1,124 +0,0 @@ -package org.apache.shenyu.web.listener; - -import com.google.common.collect.Lists; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import io.netty.handler.codec.Headers; -import org.apache.shenyu.common.concurrent.ShenyuThreadFactory; -import org.apache.shenyu.common.constant.Constants; -import org.apache.shenyu.common.constant.InstanceTypeConstants; -import org.apache.shenyu.common.dto.ConfigData; -import org.apache.shenyu.common.enums.ConfigGroupEnum; -import org.apache.shenyu.common.exception.ShenyuException; -import org.apache.shenyu.common.utils.GsonUtils; -import org.apache.shenyu.common.utils.IpUtils; -import org.apache.shenyu.common.utils.SystemInfoUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.context.event.ContextClosedEvent; -import org.springframework.context.event.EventListener; -import org.springframework.util.Assert; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.util.UriComponentsBuilder; - -import java.io.IOException; -import java.util.Collections; -import java.util.Objects; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -public class HeartbeatReporter implements ApplicationListener { - - private static final Logger LOG = LoggerFactory.getLogger(HeartbeatReporter.class); - - private ScheduledThreadPoolExecutor executor; - - - public HeartbeatReporter(ScheduledThreadPoolExecutor executor) { - executor = new ScheduledThreadPoolExecutor(1, ShenyuThreadFactory.create("scheduled-instance-task", false)); - } - - @Override - public void onApplicationEvent(ServletWebServerInitializedEvent event) { - - int port = event.getWebServer().getPort(); - LOG.info("Web server initialized on port {}, starting heartbeat reporter", port); - -// // 初始化本地IP -// localIp = getLocalIp(); -// log.info("Detected local IP: {}", localIp); - - // 启动心跳任务 -// executor.scheduleAtFixedRate(this::report, -// 0, -// 5, -// TimeUnit.SECONDS -// ); - } -// /** -// * Get the host. -// * -// * @return the host -// */ -// public String getHost() { -// return IpUtils.isCompleteHost(this.host) ? this.host -// : IpUtils.getHost(this.host); -// } -// private void report() { -// MultiValueMap params = new LinkedMultiValueMap<>(8); -// params.put("namespaceId", Collections.singletonList("1")); -// LOG.debug("listener params: [{}]", params); -// Headers headers = new Headers.Builder() -// .add(Constants.X_ACCESS_TOKEN, accessTokenManager.getAccessToken()) -// .add("Content-Type", "application/x-www-form-urlencoded") -// .add("X-Real-PORT", port + "") -// .add(InstanceTypeConstants.BOOTSTRAP_INSTANCE_INFO, SystemInfoUtils.getSystemInfo()) -// .build(); -// String listenerUrl = server + Constants.SHENYU_ADMIN_PATH_CONFIGS_LISTENER; -// String uri = UriComponentsBuilder.fromHttpUrl(listenerUrl).queryParams(params).build(true).toUriString(); -// Request request = new Request.Builder() -// .url(uri) -// .headers(headers) -// .post(RequestBody.create("", null)) -// .build(); -// -// JsonArray groupJson; -// try (Response response = okHttpClient.newCall(request).execute()) { -// if (!response.isSuccessful()) { -// String message = String.format("listener configs fail, server:[%s], http status code[%s]", server, response.code()); -// throw new ShenyuException(message); -// } -// ResponseBody responseBody = response.body(); -// Assert.notNull(responseBody, "Resolve response body failed."); -// String json = responseBody.string(); -// LOG.info("listener result: [{}]", json); -// JsonObject responseFromServer = GsonUtils.getGson().fromJson(json, JsonObject.class); -// JsonElement element = responseFromServer.get("data"); -// if (element.isJsonNull()) { -// return; -// } -// groupJson = responseFromServer.getAsJsonArray("data"); -// } catch (IOException e) { -// String message = String.format("listener configs fail, server:[%s], %s", server, e.getMessage()); -// throw new ShenyuException(message, e); -// } -// } -// -// -// @EventListener(ContextClosedEvent.class) -// public void onShutdown() { -// scheduler.shutdown(); -// try { -// if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) { -// scheduler.shutdownNow(); -// } -// } catch (InterruptedException e) { -// Thread.currentThread().interrupt(); -// } -// log.info("Heartbeat reporter shutdown complete"); -// } -} \ No newline at end of file From 275a205153c1ae160269580f3431b352dd082d5d Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Thu, 17 Jul 2025 22:18:53 +0800 Subject: [PATCH 07/17] fix --- .../admin/config/ClusterConfiguration.java | 1 + .../admin/config/StandaloneConfiguration.java | 1 + .../admin/model/entity/InstanceInfoDO.java | 2 +- .../shenyu/admin/model/vo/InstanceInfoVO.java | 4 +- .../service/impl/InstanceCheckService.java | 67 ++++++++++++------- .../service/impl/InstanceInfoServiceImpl.java | 2 +- .../client/beat/HeartbeatListener.java | 41 +++++++----- .../http/HttpClientRegisterRepository.java | 3 +- .../common/dto/InstanceBeatInfoDTO.java | 17 +++++ .../beat/HeartbeatListenerConfiguration.java | 27 +++++++- 10 files changed, 119 insertions(+), 46 deletions(-) diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/ClusterConfiguration.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/ClusterConfiguration.java index da8a63c63124..6f9eb0f23a4d 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/ClusterConfiguration.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/ClusterConfiguration.java @@ -51,6 +51,7 @@ public class ClusterConfiguration { * * @param shenyuClusterSelectMasterService shenyu cluster select master service * @param upstreamCheckService upstream check service + * @param instanceCheckService instance check service * @param loadServiceDocEntry load service doc entry * @param clusterProperties cluster properties * @return Shenyu cluster service diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/StandaloneConfiguration.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/StandaloneConfiguration.java index 50fb54b76751..3aee40f5ef68 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/StandaloneConfiguration.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/StandaloneConfiguration.java @@ -41,6 +41,7 @@ public class StandaloneConfiguration { * Shenyu running mode standalone service. * * @param upstreamCheckService upstream check service + * @param instanceCheckService instance check service * @param loadServiceDocEntry load service doc entry * @return Shenyu standalone service */ diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java index 9d19ca10800d..c74417392ec4 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java @@ -225,7 +225,7 @@ public long getLastHeartBeatTime() { * * @param lastHeartBeatTime lastHeartBeatTime */ - public void setLastHeartBeatTime(long lastHeartBeatTime) { + public void setLastHeartBeatTime(final long lastHeartBeatTime) { this.lastHeartBeatTime = lastHeartBeatTime; } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceInfoVO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceInfoVO.java index cefe01aeb2e7..722f33a78524 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceInfoVO.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceInfoVO.java @@ -213,7 +213,7 @@ public int getInstanceState() { * * @param instanceState instanceState */ - public void setInstanceState(int instanceState) { + public void setInstanceState(final int instanceState) { this.instanceState = instanceState; } @@ -231,7 +231,7 @@ public long getLastHeartBeatTime() { * * @param lastHeartBeatTime lastHeartBeatTime */ - public void setLastHeartBeatTime(long lastHeartBeatTime) { + public void setLastHeartBeatTime(final long lastHeartBeatTime) { this.lastHeartBeatTime = lastHeartBeatTime; } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java index 9f4ac6ec90f8..2f797902d578 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java @@ -1,11 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.shenyu.admin.service.impl; import jakarta.annotation.PreDestroy; -import org.apache.shenyu.register.common.dto.InstanceBeatInfoDTO; import org.apache.shenyu.admin.model.event.instance.InstanceInfoReportEvent; import org.apache.shenyu.admin.model.vo.InstanceInfoVO; import org.apache.shenyu.admin.service.InstanceInfoService; import org.apache.shenyu.common.concurrent.ShenyuThreadFactory; +import org.apache.shenyu.register.common.dto.InstanceBeatInfoDTO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.event.EventListener; @@ -13,7 +30,6 @@ import java.util.List; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -27,8 +43,6 @@ public class InstanceCheckService { private ScheduledThreadPoolExecutor executor; - private ScheduledFuture scheduledFuture; - private final int scheduledTime; private ConcurrentHashMap instanceHealthBeatInfo; @@ -40,10 +54,10 @@ public class InstanceCheckService { private InstanceInfoService instanceInfoService; - public InstanceCheckService(InstanceInfoService instanceInfoService) { + public InstanceCheckService(final InstanceInfoService instanceInfoService) { this.scheduledTime = 10; this.instanceHealthBeatInfo = new ConcurrentHashMap<>(); - this.instanceHeartBeatTimeOut = 1000 * 20; + this.instanceHeartBeatTimeOut = 1000 * 20; this.deleteTimeout = 1000 * 60; this.instanceInfoService = instanceInfoService; } @@ -65,28 +79,28 @@ public void fetchInstanceData() { List list = instanceInfoService.list(); list.forEach(instanceInfoVO -> { String instanceKey = getInstanceKey(instanceInfoVO); - instanceHealthBeatInfo.put(instanceKey,instanceInfoVO); + instanceHealthBeatInfo.put(instanceKey, instanceInfoVO); }); } - public String getInstanceKey(InstanceInfoVO instanceInfoVO){ - return instanceInfoVO.getInstanceIp()+":"+instanceInfoVO.getInstancePort()+"@"+instanceInfoVO.getInstanceType()+"#"+instanceInfoVO.getNamespaceId(); + public String getInstanceKey(final InstanceInfoVO instanceInfoVO) { + return instanceInfoVO.getInstanceIp() + ":" + instanceInfoVO.getInstancePort() + "@" + instanceInfoVO.getInstanceType() + "#" + instanceInfoVO.getNamespaceId(); } - public String getInstanceKey(InstanceBeatInfoDTO instanceBeatInfoDTO){ - return instanceBeatInfoDTO.getInstanceIp()+":"+instanceBeatInfoDTO.getInstancePort()+"@"+instanceBeatInfoDTO.getInstanceType()+"#"+instanceBeatInfoDTO.getNamespaceId(); + public String getInstanceKey(final InstanceBeatInfoDTO instanceBeatInfoDTO) { + return instanceBeatInfoDTO.getInstanceIp() + ":" + instanceBeatInfoDTO.getInstancePort() + "@" + instanceBeatInfoDTO.getInstanceType() + "#" + instanceBeatInfoDTO.getNamespaceId(); } - public InstanceInfoVO getInstanceHealthBeatInfo(InstanceBeatInfoDTO instanceBeatInfoDTO){ + public InstanceInfoVO getInstanceHealthBeatInfo(final InstanceBeatInfoDTO instanceBeatInfoDTO) { return instanceHealthBeatInfo.get(getInstanceKey(instanceBeatInfoDTO)); } - public void handleBeatInfo(InstanceBeatInfoDTO instanceBeatInfoDTO){ + public void handleBeatInfo(final InstanceBeatInfoDTO instanceBeatInfoDTO) { String instanceKey = getInstanceKey(instanceBeatInfoDTO); - if (instanceHealthBeatInfo.containsKey(instanceKey)){ + if (instanceHealthBeatInfo.containsKey(instanceKey)) { InstanceInfoVO instanceInfoVO = instanceHealthBeatInfo.get(instanceKey); instanceInfoVO.setLastHeartBeatTime(System.currentTimeMillis()); - }else { + } else { InstanceInfoVO instanceInfoVO = new InstanceInfoVO(); instanceInfoVO.setInstanceIp(instanceBeatInfoDTO.getInstanceIp()); instanceInfoVO.setInstanceState(1); @@ -96,7 +110,7 @@ public void handleBeatInfo(InstanceBeatInfoDTO instanceBeatInfoDTO){ instanceInfoVO.setInstancePort(instanceBeatInfoDTO.getInstancePort()); instanceInfoVO.setNamespaceId(instanceBeatInfoDTO.getNamespaceId()); instanceInfoVO.setLastHeartBeatTime(System.currentTimeMillis()); - instanceHealthBeatInfo.put(instanceKey,instanceInfoVO); + instanceHealthBeatInfo.put(instanceKey, instanceInfoVO); } } @@ -112,27 +126,31 @@ private void doCheck() { instanceHealthBeatInfo.values().forEach(instance -> { if (System.currentTimeMillis() - instance.getLastHeartBeatTime() > instanceHeartBeatTimeOut) { if (1 == instance.getInstanceState()) { - LOG.info("[instanceHealthInfo]namespace:{},type:{},Ip:{},Port:{} offline!", instance.getNamespaceId(), instance.getInstanceType(), instance.getInstanceIp(), instance.getInstancePort()); + LOG.info("[instanceHealthInfo]namespace:{},type:{},Ip:{},Port:{} offline!", + instance.getNamespaceId(), instance.getInstanceType(), instance.getInstanceIp(), instance.getInstancePort()); instance.setInstanceState(2); } - }else{ - LOG.info("[instanceHealthInfo]namespace:{},type:{},Ip:{},Port:{} online!", instance.getNamespaceId(), instance.getInstanceType(), instance.getInstanceIp(), instance.getInstancePort()); + } else { + LOG.info("[instanceHealthInfo]namespace:{},type:{},Ip:{},Port:{} online!", + instance.getNamespaceId(), instance.getInstanceType(), instance.getInstanceIp(), instance.getInstancePort()); instance.setInstanceState(1); } if (System.currentTimeMillis() - instance.getLastHeartBeatTime() > deleteTimeout) { if (2 == instance.getInstanceState()) { - LOG.info("[instanceHealthInfo]namespace:{},type:{},Ip:{},Port:{} deleted!", instance.getNamespaceId(), instance.getInstanceType(), instance.getInstanceIp(), instance.getInstancePort()); + LOG.info("[instanceHealthInfo]namespace:{},type:{},Ip:{},Port:{} deleted!", + instance.getNamespaceId(), instance.getInstanceType(), instance.getInstanceIp(), instance.getInstancePort()); instance.setInstanceState(0); } } }); } - public void syncDB(){ - instanceHealthBeatInfo.values().forEach(vo->{ + public void syncDB() { + instanceHealthBeatInfo.values().forEach(vo -> { instanceInfoService.createOrUpdate(vo); }); } + /** * Close relative resource on container destroy. */ @@ -141,6 +159,7 @@ public void close() { syncDB(); executor.shutdown(); } + /** * listen {@link InstanceInfoReportEvent} instance info report event. * @@ -148,8 +167,8 @@ public void close() { */ @EventListener(InstanceInfoReportEvent.class) public void onInstanceInfoReport(final InstanceInfoReportEvent event) { - InstanceBeatInfoDTO InstanceBeatInfoDTO = buildInstanceInfoDTO(event); - handleBeatInfo(InstanceBeatInfoDTO); + InstanceBeatInfoDTO instanceBeatInfoDTO = buildInstanceInfoDTO(event); + handleBeatInfo(instanceBeatInfoDTO); } private InstanceBeatInfoDTO buildInstanceInfoDTO(final InstanceInfoReportEvent instanceInfoRegisterDTO) { diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java index c50a93111e03..367905f588d5 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java @@ -49,7 +49,7 @@ public InstanceInfoServiceImpl(final InstanceInfoMapper instanceInfoMapper) { } @Override - public void createOrUpdate(InstanceInfoVO instanceInfoVO) { + public void createOrUpdate(final InstanceInfoVO instanceInfoVO) { InstanceQuery instanceQuery = new InstanceQuery(); instanceQuery.setInstanceIp(instanceInfoVO.getInstanceIp()); instanceQuery.setInstancePort(instanceInfoVO.getInstancePort()); diff --git a/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java b/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java index 3a207457b568..e7ee611cb96d 100644 --- a/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java +++ b/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java @@ -1,3 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.shenyu.register.client.beat; import org.apache.shenyu.common.concurrent.ShenyuThreadFactory; @@ -6,20 +23,17 @@ import org.apache.shenyu.common.utils.IpUtils; import org.apache.shenyu.common.utils.SystemInfoUtils; import org.apache.shenyu.register.client.api.ShenyuClientRegisterRepository; -import org.apache.shenyu.register.client.http.HttpClientRegisterRepository; import org.apache.shenyu.register.common.dto.InstanceBeatInfoDTO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent; -import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.EventListener; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -public class HeartbeatListener{ +public class HeartbeatListener { private static final Logger LOG = LoggerFactory.getLogger(HeartbeatListener.class); @@ -36,17 +50,14 @@ public HeartbeatListener(final ShenyuClientRegisterRepository httpClientRegister LOG.info("Web server initialized on port {}, starting heartbeat reporter", serverProperties.getPort()); //启动心跳任务 executor.scheduleAtFixedRate(() -> { - InstanceBeatInfoDTO instanceBeatInfoDTO = new InstanceBeatInfoDTO(); - instanceBeatInfoDTO.setInstancePort(serverProperties.getPort()+""); - instanceBeatInfoDTO.setInstanceIp(IpUtils.getHost()); - instanceBeatInfoDTO.setNamespaceId(shenyuConfig.getNamespace()); - instanceBeatInfoDTO.setInstanceInfo(SystemInfoUtils.getSystemInfo()); - instanceBeatInfoDTO.setInstanceType(InstanceTypeConstants.BOOTSTRAP_INSTANCE_INFO); - httpClientRegisterRepository.sendHeartbeat(instanceBeatInfoDTO); - }, - 0, - 5, - TimeUnit.SECONDS + InstanceBeatInfoDTO instanceBeatInfoDTO = new InstanceBeatInfoDTO(); + instanceBeatInfoDTO.setInstancePort(serverProperties.getPort() + ""); + instanceBeatInfoDTO.setInstanceIp(IpUtils.getHost()); + instanceBeatInfoDTO.setNamespaceId(shenyuConfig.getNamespace()); + instanceBeatInfoDTO.setInstanceInfo(SystemInfoUtils.getSystemInfo()); + instanceBeatInfoDTO.setInstanceType(InstanceTypeConstants.BOOTSTRAP_INSTANCE_INFO); + httpClientRegisterRepository.sendHeartbeat(instanceBeatInfoDTO); + }, 0, 5, TimeUnit.SECONDS ); } diff --git a/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/main/java/org/apache/shenyu/register/client/http/HttpClientRegisterRepository.java b/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/main/java/org/apache/shenyu/register/client/http/HttpClientRegisterRepository.java index b828baaed8e7..71adc4c229ab 100644 --- a/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/main/java/org/apache/shenyu/register/client/http/HttpClientRegisterRepository.java +++ b/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/main/java/org/apache/shenyu/register/client/http/HttpClientRegisterRepository.java @@ -141,9 +141,10 @@ public void sendHeartbeat(final URIRegisterDTO heartbeatDTO) { } @Override - public void sendHeartbeat(InstanceBeatInfoDTO instanceBeatInfoDTO) { + public void sendHeartbeat(final InstanceBeatInfoDTO instanceBeatInfoDTO) { doHeartbeat(instanceBeatInfoDTO, Constants.BEAT_URI_PATH); } + /** * doPersistApiDoc. * diff --git a/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/InstanceBeatInfoDTO.java b/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/InstanceBeatInfoDTO.java index 89016396efcc..410364c5d99b 100644 --- a/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/InstanceBeatInfoDTO.java +++ b/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/dto/InstanceBeatInfoDTO.java @@ -1,3 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.shenyu.register.common.dto; public class InstanceBeatInfoDTO { diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListenerConfiguration.java b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListenerConfiguration.java index 005e432a1103..a38d03815d3a 100644 --- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListenerConfiguration.java +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListenerConfiguration.java @@ -1,8 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.shenyu.register.client.beat; import org.apache.shenyu.common.config.ShenyuConfig; import org.apache.shenyu.register.client.api.ShenyuClientRegisterRepository; -import org.apache.shenyu.register.client.http.HttpClientRegisterRepository; import org.apache.shenyu.springboot.starter.client.common.config.ShenyuClientCommonBeanConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -15,7 +31,14 @@ @ConditionalOnProperty(value = "shenyu.register.enabled", matchIfMissing = true, havingValue = "true") public class HeartbeatListenerConfiguration { - + /** + * Heartbeat bean listener. + * + * @param httpClientRegisterRepository the http client register repository + * @param shenyuConfig the shenyu config + * @param serverProperties the server properties + * @return the heartbeat bean listener. + */ @Bean public HeartbeatListener heartbeatListener(final ShenyuClientRegisterRepository httpClientRegisterRepository, final ShenyuConfig shenyuConfig, From c85ddff9d5f969d264fec5de7349dcd9469b5372 Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Sat, 19 Jul 2025 17:39:42 +0800 Subject: [PATCH 08/17] 'fix' --- .../shenyu-register-client-beat/pom.xml | 18 +++++++++++++++++- .../pom.xml | 18 +++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/shenyu-register-center/shenyu-register-client-beat/pom.xml b/shenyu-register-center/shenyu-register-client-beat/pom.xml index 6f18cfda2558..6f9c8fb52a8b 100644 --- a/shenyu-register-center/shenyu-register-client-beat/pom.xml +++ b/shenyu-register-center/shenyu-register-client-beat/pom.xml @@ -1,4 +1,20 @@ + @@ -28,4 +44,4 @@ provided - \ No newline at end of file + diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/pom.xml b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/pom.xml index ad9b6690e8d2..5d8fc8a2194a 100644 --- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/pom.xml +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/pom.xml @@ -1,4 +1,20 @@ + @@ -29,4 +45,4 @@ ${project.version} - \ No newline at end of file + From 410340d097e7a505d3ac8fbc1d031086e3d29364 Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Thu, 21 Aug 2025 23:36:54 +0800 Subject: [PATCH 09/17] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=8F=AF=E8=A7=86?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/controller/InstanceController.java | 18 +++++ .../model/vo/InstanceDataVisualLineVO.java | 33 ++++++++ .../admin/model/vo/InstanceDataVisualVO.java | 25 +++++++ .../service/impl/InstanceCheckService.java | 75 +++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualLineVO.java create mode 100644 shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualVO.java diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java index 2ff8dcd0f228..90a541da4c3e 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java @@ -80,6 +80,13 @@ public ShenyuAdminResult queryPlugins(@RequestParam(name = "instanceType", requi namespaceId ) ); + commonPager.getDataList().forEach(instanceInfoVO -> { + String instanceKey = instanceCheckService.getInstanceKey(instanceInfoVO); + InstanceInfoVO instanceHealthBeatInfo = instanceCheckService.getInstanceHealthBeatInfo(instanceKey); + instanceInfoVO.setLastHeartBeatTime(instanceHealthBeatInfo.getLastHeartBeatTime()); + instanceInfoVO.setInstanceState(instanceHealthBeatInfo.getInstanceState()); + instanceInfoVO.setDateUpdated(instanceHealthBeatInfo.getDateUpdated()); + }); return ShenyuAdminResult.success(ShenyuResultMessage.QUERY_SUCCESS, commonPager); } @@ -109,6 +116,17 @@ public String beat(@Valid @RequestBody final InstanceBeatInfoDTO instanceBeatInf return ShenyuResultMessage.SUCCESS; } + /** + * visual instance info. + * + * @param namespaceId namespace id. + * @return {@linkplain ShenyuAdminResult} + */ + @GetMapping("/analysis/{namespaceId}") + public ShenyuAdminResult getInstanceDataVisual(@PathVariable("namespaceId") final String namespaceId) { + return ShenyuAdminResult.success(ShenyuResultMessage.QUERY_SUCCESS, instanceCheckService.getInstanceDataVisual(namespaceId)); + } + diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualLineVO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualLineVO.java new file mode 100644 index 000000000000..30b35e2805b1 --- /dev/null +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualLineVO.java @@ -0,0 +1,33 @@ +package org.apache.shenyu.admin.model.vo; + +import java.util.List; + +public class InstanceDataVisualLineVO { + + public InstanceDataVisualLineVO() { + } + + public InstanceDataVisualLineVO(String name, List date) { + this.name = name; + this.date = date; + } + + private String name; + private List date; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getDate() { + return date; + } + + public void setDate(List date) { + this.date = date; + } +} diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualVO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualVO.java new file mode 100644 index 000000000000..a295034cf911 --- /dev/null +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualVO.java @@ -0,0 +1,25 @@ +package org.apache.shenyu.admin.model.vo; + +import java.util.List; +import java.util.Map; + +public class InstanceDataVisualVO { + Map pieData; + List lineList; + + public Map getPieData() { + return pieData; + } + + public void setPieData(Map pieData) { + this.pieData = pieData; + } + + public List getLineList() { + return lineList; + } + + public void setLineList(List lineList) { + this.lineList = lineList; + } +} diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java index 2f797902d578..fa3e322edd9b 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java @@ -18,7 +18,10 @@ package org.apache.shenyu.admin.service.impl; import jakarta.annotation.PreDestroy; +import org.apache.commons.lang3.StringUtils; import org.apache.shenyu.admin.model.event.instance.InstanceInfoReportEvent; +import org.apache.shenyu.admin.model.vo.InstanceDataVisualLineVO; +import org.apache.shenyu.admin.model.vo.InstanceDataVisualVO; import org.apache.shenyu.admin.model.vo.InstanceInfoVO; import org.apache.shenyu.admin.service.InstanceInfoService; import org.apache.shenyu.common.concurrent.ShenyuThreadFactory; @@ -27,11 +30,20 @@ import org.slf4j.LoggerFactory; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Deque; import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; /** * This is the client check service. @@ -53,6 +65,9 @@ public class InstanceCheckService { private InstanceInfoService instanceInfoService; + private final Map> stateHistoryMap; + + private static final int MAX_HISTORY_SIZE = 20; public InstanceCheckService(final InstanceInfoService instanceInfoService) { this.scheduledTime = 10; @@ -60,6 +75,7 @@ public InstanceCheckService(final InstanceInfoService instanceInfoService) { this.instanceHeartBeatTimeOut = 1000 * 20; this.deleteTimeout = 1000 * 60; this.instanceInfoService = instanceInfoService; + this.stateHistoryMap = new ConcurrentHashMap<>(); } /** @@ -95,6 +111,10 @@ public InstanceInfoVO getInstanceHealthBeatInfo(final InstanceBeatInfoDTO instan return instanceHealthBeatInfo.get(getInstanceKey(instanceBeatInfoDTO)); } + public InstanceInfoVO getInstanceHealthBeatInfo(final String instanceKey) { + return instanceHealthBeatInfo.get(instanceKey); + } + public void handleBeatInfo(final InstanceBeatInfoDTO instanceBeatInfoDTO) { String instanceKey = getInstanceKey(instanceBeatInfoDTO); if (instanceHealthBeatInfo.containsKey(instanceKey)) { @@ -142,6 +162,7 @@ private void doCheck() { instance.setInstanceState(0); } } + collectStateData(); }); } @@ -180,4 +201,58 @@ private InstanceBeatInfoDTO buildInstanceInfoDTO(final InstanceInfoReportEvent i instanceInfoDTO.setNamespaceId(instanceInfoRegisterDTO.getNamespaceId()); return instanceInfoDTO; } + + private void collectStateData() { + if (!CollectionUtils.isEmpty(instanceHealthBeatInfo)) { + Map pieData = instanceHealthBeatInfo.values().stream().collect(Collectors.groupingBy(InstanceInfoVO::getInstanceState, Collectors.counting())); + updateStateHistory(pieData); + } + } + + public InstanceDataVisualVO getInstanceDataVisual(String namespaceId) { + InstanceDataVisualVO instanceDataVisualVO = new InstanceDataVisualVO(); + List instanceInfoVOS = instanceHealthBeatInfo.values().stream().toList(); + if (StringUtils.isNotBlank(namespaceId)) { + instanceInfoVOS = instanceInfoVOS.stream().filter(vo -> namespaceId.equals(vo.getNamespaceId())).collect(Collectors.toList()); + } + Map pieData = instanceInfoVOS.stream().collect(Collectors.groupingBy(InstanceInfoVO::getInstanceState, Collectors.counting())); + List lineList = new ArrayList<>(); + for (Integer state : Arrays.asList(0, 1, 2)) { + Deque queue = stateHistoryMap.get(state); + List data = new ArrayList<>(queue); + while (data.size() < MAX_HISTORY_SIZE) { + data.add(0, 0L); + } + InstanceDataVisualLineVO dto = new InstanceDataVisualLineVO( + state + "", + data + ); + lineList.add(dto); + } + instanceDataVisualVO.setPieData(pieData); + instanceDataVisualVO.setLineList(lineList); + return instanceDataVisualVO; + } + + + private void updateStateHistory(Map currentData) { + ensureStateQueues(); + for (Integer state : Arrays.asList(0, 1, 2)) { + Long count = currentData.getOrDefault(state, 0L); + Deque queue = stateHistoryMap.get(state); + queue.addLast(count); + while (queue.size() > MAX_HISTORY_SIZE) { + queue.removeFirst(); + } + } + } + + /** + * 确保所有状态都有对应的数据队列 + */ + private void ensureStateQueues() { + for (Integer state : Arrays.asList(0, 1, 2)) { + stateHistoryMap.putIfAbsent(state, new ConcurrentLinkedDeque<>()); + } + } } From 19a13b4a8b37bacaf6655d0e47cd05f06fc274c6 Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Sun, 31 Aug 2025 14:33:17 +0800 Subject: [PATCH 10/17] =?UTF-8?q?=E5=9B=BE=E6=A0=87=E5=8F=AF=E8=A7=86?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/vo/InstanceDataVisualLineVO.java | 53 ++++++++-- .../admin/model/vo/InstanceDataVisualVO.java | 100 ++++++++++++++++-- .../service/impl/InstanceCheckService.java | 33 +++--- .../common/enums/InstanceStatusEnum.java | 64 +++++++++++ 4 files changed, 219 insertions(+), 31 deletions(-) create mode 100644 shenyu-common/src/main/java/org/apache/shenyu/common/enums/InstanceStatusEnum.java diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualLineVO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualLineVO.java index 30b35e2805b1..d4bdc88660c2 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualLineVO.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualLineVO.java @@ -1,3 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.shenyu.admin.model.vo; import java.util.List; @@ -7,27 +24,49 @@ public class InstanceDataVisualLineVO { public InstanceDataVisualLineVO() { } - public InstanceDataVisualLineVO(String name, List date) { + public InstanceDataVisualLineVO(String name, List data) { this.name = name; - this.date = date; + this.data = data; } private String name; - private List date; + private List data; + + /** + * Gets the value of name. + * + * @return the value of name + */ public String getName() { return name; } + /** + * set name. + * + * @param name name + */ public void setName(String name) { this.name = name; } - public List getDate() { - return date; + /** + * Gets the value of data. + * + * @return the value of data + */ + public List getData() { + return data; } - public void setDate(List date) { - this.date = date; + /** + * set data. + * + * @param data data + */ + public void setData(List data) { + this.data = data; } + } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualVO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualVO.java index a295034cf911..e575ba505d90 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualVO.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualVO.java @@ -1,25 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.apache.shenyu.admin.model.vo; + import java.util.List; -import java.util.Map; public class InstanceDataVisualVO { - Map pieData; - List lineList; + List pieData; + List lineData; - public Map getPieData() { + /** + * Gets the value of pieData. + * + * @return the value of pieData + */ + public List getPieData() { return pieData; } - public void setPieData(Map pieData) { + /** + * set pieData. + * + * @param pieData pieData + */ + public void setPieData(List pieData) { this.pieData = pieData; } - public List getLineList() { - return lineList; + /** + * Gets the value of lineData. + * + * @return the value of lineData + */ + public List getLineData() { + return lineData; + } + + /** + * set lineData. + * + * @param lineData lineData + */ + public void setLineData(List lineData) { + this.lineData = lineData; } + public static class Entry { + private String name; + private Long value; + + public Entry(String name, Long value) { + this.name = name; + this.value = value; + } + + /** + * Gets the value of name. + * + * @return the value of name + */ + public String getName() { + return name; + } + + /** + * set name. + * + * @param name name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Gets the value . + * + * @return the value + */ + public Long getValue() { + return value; + } - public void setLineList(List lineList) { - this.lineList = lineList; + /** + * set value. + * + * @param value value + */ + public void setValue(Long value) { + this.value = value; + } } } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java index fa3e322edd9b..710da05a9951 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java @@ -25,6 +25,7 @@ import org.apache.shenyu.admin.model.vo.InstanceInfoVO; import org.apache.shenyu.admin.service.InstanceInfoService; import org.apache.shenyu.common.concurrent.ShenyuThreadFactory; +import org.apache.shenyu.common.enums.InstanceStatusEnum; import org.apache.shenyu.register.common.dto.InstanceBeatInfoDTO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,10 +33,9 @@ import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; import java.util.Deque; import java.util.List; import java.util.Map; @@ -145,21 +145,21 @@ private void scheduled() { private void doCheck() { instanceHealthBeatInfo.values().forEach(instance -> { if (System.currentTimeMillis() - instance.getLastHeartBeatTime() > instanceHeartBeatTimeOut) { - if (1 == instance.getInstanceState()) { + if (InstanceStatusEnum.ONLINE.getCode() == instance.getInstanceState()) { LOG.info("[instanceHealthInfo]namespace:{},type:{},Ip:{},Port:{} offline!", instance.getNamespaceId(), instance.getInstanceType(), instance.getInstanceIp(), instance.getInstancePort()); - instance.setInstanceState(2); + instance.setInstanceState(InstanceStatusEnum.OFFLINE.getCode()); } } else { LOG.info("[instanceHealthInfo]namespace:{},type:{},Ip:{},Port:{} online!", instance.getNamespaceId(), instance.getInstanceType(), instance.getInstanceIp(), instance.getInstancePort()); - instance.setInstanceState(1); + instance.setInstanceState(InstanceStatusEnum.ONLINE.getCode()); } if (System.currentTimeMillis() - instance.getLastHeartBeatTime() > deleteTimeout) { - if (2 == instance.getInstanceState()) { + if (InstanceStatusEnum.OFFLINE.getCode() == instance.getInstanceState()) { LOG.info("[instanceHealthInfo]namespace:{},type:{},Ip:{},Port:{} deleted!", instance.getNamespaceId(), instance.getInstanceType(), instance.getInstanceIp(), instance.getInstancePort()); - instance.setInstanceState(0); + instance.setInstanceState(InstanceStatusEnum.DELETED.getCode()); } } collectStateData(); @@ -218,23 +218,29 @@ public InstanceDataVisualVO getInstanceDataVisual(String namespaceId) { Map pieData = instanceInfoVOS.stream().collect(Collectors.groupingBy(InstanceInfoVO::getInstanceState, Collectors.counting())); List lineList = new ArrayList<>(); for (Integer state : Arrays.asList(0, 1, 2)) { - Deque queue = stateHistoryMap.get(state); + Deque queue = stateHistoryMap.getOrDefault(state, new ArrayDeque<>(MAX_HISTORY_SIZE)); List data = new ArrayList<>(queue); while (data.size() < MAX_HISTORY_SIZE) { data.add(0, 0L); } InstanceDataVisualLineVO dto = new InstanceDataVisualLineVO( - state + "", + InstanceStatusEnum.getNameByCode(state), data ); lineList.add(dto); } - instanceDataVisualVO.setPieData(pieData); - instanceDataVisualVO.setLineList(lineList); + List pieDataList = pieData.entrySet().stream() + .map(entry -> { + Integer stateCode = entry.getKey(); + String stateName = InstanceStatusEnum.getNameByCode(stateCode); // 需要添加这个方法 + return new InstanceDataVisualVO.Entry(stateName, entry.getValue()); + }) + .collect(Collectors.toList()); + instanceDataVisualVO.setPieData(pieDataList); + instanceDataVisualVO.setLineData(lineList); return instanceDataVisualVO; } - private void updateStateHistory(Map currentData) { ensureStateQueues(); for (Integer state : Arrays.asList(0, 1, 2)) { @@ -247,9 +253,6 @@ private void updateStateHistory(Map currentData) { } } - /** - * 确保所有状态都有对应的数据队列 - */ private void ensureStateQueues() { for (Integer state : Arrays.asList(0, 1, 2)) { stateHistoryMap.putIfAbsent(state, new ConcurrentLinkedDeque<>()); diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/InstanceStatusEnum.java b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/InstanceStatusEnum.java new file mode 100644 index 000000000000..6093ce5754ac --- /dev/null +++ b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/InstanceStatusEnum.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shenyu.common.enums; + +import java.util.function.Function; + +public enum InstanceStatusEnum { + + /** + * OFFLINE. + */ + OFFLINE(2, "OFFLINE"), + + /** + * ONLINE. + */ + ONLINE(1, "ONLINE"), + + /** + * DELETED. + */ + DELETED(0, "DELETED"); + + private final int code; + + private final String name; + + InstanceStatusEnum(int code, String name) { + this.code = code; + this.name = name; + } + + public int getCode() { + return code; + } + + public String getName() { + return name; + } + + public static String getNameByCode(int code) { + for (InstanceStatusEnum status : values()) { + if (status.getCode() == code) { + return status.getName(); + } + } + return "UNKNOWN"; + } +} From e8235fae6a3bfb48920bd88a1be0451856f48dc6 Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Sun, 31 Aug 2025 15:12:08 +0800 Subject: [PATCH 11/17] =?UTF-8?q?=E5=8F=AF=E8=A7=86=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/vo/InstanceDataVisualLineVO.java | 14 +++++++------- .../admin/model/vo/InstanceDataVisualVO.java | 19 ++++++++++++------- .../service/impl/InstanceCheckService.java | 10 +++++----- .../common/enums/InstanceStatusEnum.java | 6 ++---- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualLineVO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualLineVO.java index d4bdc88660c2..e2dd0960dfd9 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualLineVO.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualLineVO.java @@ -21,18 +21,18 @@ public class InstanceDataVisualLineVO { + private String name; + + private List data; + public InstanceDataVisualLineVO() { } - public InstanceDataVisualLineVO(String name, List data) { + public InstanceDataVisualLineVO(final String name, final List data) { this.name = name; this.data = data; } - private String name; - private List data; - - /** * Gets the value of name. * @@ -47,7 +47,7 @@ public String getName() { * * @param name name */ - public void setName(String name) { + public void setName(final String name) { this.name = name; } @@ -65,7 +65,7 @@ public List getData() { * * @param data data */ - public void setData(List data) { + public void setData(final List data) { this.data = data; } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualVO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualVO.java index e575ba505d90..202dd71aa5e2 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualVO.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceDataVisualVO.java @@ -21,8 +21,10 @@ import java.util.List; public class InstanceDataVisualVO { - List pieData; - List lineData; + + private List pieData; + + private List lineData; /** * Gets the value of pieData. @@ -38,7 +40,7 @@ public List getPieData() { * * @param pieData pieData */ - public void setPieData(List pieData) { + public void setPieData(final List pieData) { this.pieData = pieData; } @@ -56,14 +58,17 @@ public List getLineData() { * * @param lineData lineData */ - public void setLineData(List lineData) { + public void setLineData(final List lineData) { this.lineData = lineData; } + public static class Entry { + private String name; + private Long value; - public Entry(String name, Long value) { + public Entry(final String name, final Long value) { this.name = name; this.value = value; } @@ -82,7 +87,7 @@ public String getName() { * * @param name name */ - public void setName(String name) { + public void setName(final String name) { this.name = name; } @@ -100,7 +105,7 @@ public Long getValue() { * * @param value value */ - public void setValue(Long value) { + public void setValue(final Long value) { this.value = value; } } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java index 710da05a9951..933739a07b54 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java @@ -51,6 +51,8 @@ @Component public class InstanceCheckService { + private static final int MAX_HISTORY_SIZE = 20; + private static final Logger LOG = LoggerFactory.getLogger(UpstreamCheckService.class); private ScheduledThreadPoolExecutor executor; @@ -67,8 +69,6 @@ public class InstanceCheckService { private final Map> stateHistoryMap; - private static final int MAX_HISTORY_SIZE = 20; - public InstanceCheckService(final InstanceInfoService instanceInfoService) { this.scheduledTime = 10; this.instanceHealthBeatInfo = new ConcurrentHashMap<>(); @@ -209,7 +209,7 @@ private void collectStateData() { } } - public InstanceDataVisualVO getInstanceDataVisual(String namespaceId) { + public InstanceDataVisualVO getInstanceDataVisual(final String namespaceId) { InstanceDataVisualVO instanceDataVisualVO = new InstanceDataVisualVO(); List instanceInfoVOS = instanceHealthBeatInfo.values().stream().toList(); if (StringUtils.isNotBlank(namespaceId)) { @@ -232,7 +232,7 @@ public InstanceDataVisualVO getInstanceDataVisual(String namespaceId) { List pieDataList = pieData.entrySet().stream() .map(entry -> { Integer stateCode = entry.getKey(); - String stateName = InstanceStatusEnum.getNameByCode(stateCode); // 需要添加这个方法 + String stateName = InstanceStatusEnum.getNameByCode(stateCode); return new InstanceDataVisualVO.Entry(stateName, entry.getValue()); }) .collect(Collectors.toList()); @@ -241,7 +241,7 @@ public InstanceDataVisualVO getInstanceDataVisual(String namespaceId) { return instanceDataVisualVO; } - private void updateStateHistory(Map currentData) { + private void updateStateHistory(final Map currentData) { ensureStateQueues(); for (Integer state : Arrays.asList(0, 1, 2)) { Long count = currentData.getOrDefault(state, 0L); diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/InstanceStatusEnum.java b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/InstanceStatusEnum.java index 6093ce5754ac..2d01afa579af 100644 --- a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/InstanceStatusEnum.java +++ b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/InstanceStatusEnum.java @@ -17,8 +17,6 @@ package org.apache.shenyu.common.enums; -import java.util.function.Function; - public enum InstanceStatusEnum { /** @@ -40,7 +38,7 @@ public enum InstanceStatusEnum { private final String name; - InstanceStatusEnum(int code, String name) { + InstanceStatusEnum(final int code, final String name) { this.code = code; this.name = name; } @@ -53,7 +51,7 @@ public String getName() { return name; } - public static String getNameByCode(int code) { + public static String getNameByCode(final int code) { for (InstanceStatusEnum status : values()) { if (status.getCode() == code) { return status.getName(); From 6d795b59c280ba55c7d56e43e0003d7cd7eb09f1 Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Thu, 4 Sep 2025 20:34:19 +0800 Subject: [PATCH 12/17] fix cr --- .../admin/controller/InstanceController.java | 41 +++++++++---------- .../client/beat/HeartbeatListener.java | 6 ++- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java index 90a541da4c3e..ff515f39974b 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java @@ -32,6 +32,7 @@ import org.apache.shenyu.admin.service.impl.InstanceCheckService; import org.apache.shenyu.admin.utils.ShenyuResultMessage; import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -59,9 +60,9 @@ public InstanceController(final InstanceInfoService instanceInfoService, final I * @param instanceType instance type. * @param instanceIp instance ip. * @param instancePort instance port. - * @param namespaceId namespace id. - * @param currentPage current page. - * @param pageSize page size. + * @param namespaceId namespace id. + * @param currentPage current page. + * @param pageSize page size. * @return {@linkplain ShenyuAdminResult} */ @GetMapping @@ -72,21 +73,23 @@ public ShenyuAdminResult queryPlugins(@RequestParam(name = "instanceType", requi @NotNull @RequestParam(name = "currentPage") final Integer currentPage, @NotNull @RequestParam(name = "pageSize") final Integer pageSize) { CommonPager commonPager = instanceInfoService.listByPage( - new InstanceQuery( - new PageParameter(currentPage, pageSize), - instanceType, - instanceIp, - instancePort, - namespaceId - ) + new InstanceQuery( + new PageParameter(currentPage, pageSize), + instanceType, + instanceIp, + instancePort, + namespaceId + ) ); - commonPager.getDataList().forEach(instanceInfoVO -> { - String instanceKey = instanceCheckService.getInstanceKey(instanceInfoVO); - InstanceInfoVO instanceHealthBeatInfo = instanceCheckService.getInstanceHealthBeatInfo(instanceKey); - instanceInfoVO.setLastHeartBeatTime(instanceHealthBeatInfo.getLastHeartBeatTime()); - instanceInfoVO.setInstanceState(instanceHealthBeatInfo.getInstanceState()); - instanceInfoVO.setDateUpdated(instanceHealthBeatInfo.getDateUpdated()); - }); + if (!CollectionUtils.isEmpty(commonPager.getDataList())) { + commonPager.getDataList().forEach(instanceInfoVO -> { + String instanceKey = instanceCheckService.getInstanceKey(instanceInfoVO); + InstanceInfoVO instanceHealthBeatInfo = instanceCheckService.getInstanceHealthBeatInfo(instanceKey); + instanceInfoVO.setLastHeartBeatTime(instanceHealthBeatInfo.getLastHeartBeatTime()); + instanceInfoVO.setInstanceState(instanceHealthBeatInfo.getInstanceState()); + instanceInfoVO.setDateUpdated(instanceHealthBeatInfo.getDateUpdated()); + }); + } return ShenyuAdminResult.success(ShenyuResultMessage.QUERY_SUCCESS, commonPager); } @@ -111,7 +114,6 @@ public ShenyuAdminResult detailInstanceInfo(@PathVariable("id") final String id) */ @PostMapping("/beat") public String beat(@Valid @RequestBody final InstanceBeatInfoDTO instanceBeatInfoDTO) { - //todo:admin集群模式下,请求转发给master节点 instanceCheckService.handleBeatInfo(instanceBeatInfoDTO); return ShenyuResultMessage.SUCCESS; } @@ -128,9 +130,6 @@ public ShenyuAdminResult getInstanceDataVisual(@PathVariable("namespaceId") fina } - - - @Override public PageService pageService() { return instanceInfoService; diff --git a/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java b/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java index e7ee611cb96d..b12aad53262e 100644 --- a/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java +++ b/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java @@ -37,6 +37,10 @@ public class HeartbeatListener { private static final Logger LOG = LoggerFactory.getLogger(HeartbeatListener.class); + private static final int INITIAL_DELAY=0; + + private static final int CHECK_PERIOD=5; + private ScheduledThreadPoolExecutor executor; private final ShenyuClientRegisterRepository httpClientRegisterRepository; @@ -57,7 +61,7 @@ public HeartbeatListener(final ShenyuClientRegisterRepository httpClientRegister instanceBeatInfoDTO.setInstanceInfo(SystemInfoUtils.getSystemInfo()); instanceBeatInfoDTO.setInstanceType(InstanceTypeConstants.BOOTSTRAP_INSTANCE_INFO); httpClientRegisterRepository.sendHeartbeat(instanceBeatInfoDTO); - }, 0, 5, TimeUnit.SECONDS + }, INITIAL_DELAY, CHECK_PERIOD, TimeUnit.SECONDS ); } From 2da6bf0f41586c40b108066aff958a457e60b411 Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Thu, 4 Sep 2025 21:30:57 +0800 Subject: [PATCH 13/17] fix cr --- shenyu-register-center/shenyu-register-client-beat/pom.xml | 2 +- .../apache/shenyu/register/client/beat/HeartbeatListener.java | 4 ++-- .../shenyu-spring-boot-starter-client-beat/pom.xml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/shenyu-register-center/shenyu-register-client-beat/pom.xml b/shenyu-register-center/shenyu-register-client-beat/pom.xml index 6f9c8fb52a8b..8e7933dd2ec0 100644 --- a/shenyu-register-center/shenyu-register-client-beat/pom.xml +++ b/shenyu-register-center/shenyu-register-client-beat/pom.xml @@ -21,7 +21,7 @@ org.apache.shenyu shenyu-register-center - 2.7.0.2-SNAPSHOT + 2.7.0.3-SNAPSHOT 4.0.0 diff --git a/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java b/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java index b12aad53262e..662e073fd3d9 100644 --- a/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java +++ b/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java @@ -37,9 +37,9 @@ public class HeartbeatListener { private static final Logger LOG = LoggerFactory.getLogger(HeartbeatListener.class); - private static final int INITIAL_DELAY=0; + private static final int INITIAL_DELAY = 0; - private static final int CHECK_PERIOD=5; + private static final int CHECK_PERIOD = 5; private ScheduledThreadPoolExecutor executor; diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/pom.xml b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/pom.xml index 5d8fc8a2194a..61c7c53eff76 100644 --- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/pom.xml +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-beat/pom.xml @@ -21,7 +21,7 @@ org.apache.shenyu shenyu-spring-boot-starter-client - 2.7.0.2-SNAPSHOT + 2.7.0.3-SNAPSHOT 4.0.0 From a2bcd4edc817d3c2b22b374587e4b744181d8ae5 Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Thu, 4 Sep 2025 21:53:31 +0800 Subject: [PATCH 14/17] fix cr --- shenyu-common/pom.xml | 10 +-- .../shenyu/common/utils/SystemInfoUtils.java | 68 +++++++++++++++++++ 2 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java diff --git a/shenyu-common/pom.xml b/shenyu-common/pom.xml index 64ca38c5ab56..a9c4dbbb3188 100644 --- a/shenyu-common/pom.xml +++ b/shenyu-common/pom.xml @@ -89,11 +89,11 @@ bcprov-jdk18on - - - - - + + com.github.oshi + oshi-core + 6.7.0 + diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java new file mode 100644 index 000000000000..b137abc440a9 --- /dev/null +++ b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shenyu.common.utils; + +import com.sun.management.OperatingSystemMXBean; +import oshi.SystemInfo; + +import java.lang.management.ManagementFactory; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Map; + +/** + * The type System info utils. + */ +public final class SystemInfoUtils { + + /** + * Gets system info. + * + * @return the system info + */ + public static String getSystemInfo() { + try { + // Get host information using OSHI + SystemInfo systemInfo = new SystemInfo(); + + // Get host information + OperatingSystemMXBean osBean = + (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); + Map hostInfo = Map.of( + "arch", osBean.getArch(), + "operatingSystem", systemInfo.getOperatingSystem().toString(), + "availableProcessors", osBean.getAvailableProcessors(), + "totalMemorySizeGB", bytesToGB(osBean.getTotalMemorySize()) + " GB" + ); + return GsonUtils.getInstance().toJson(hostInfo); + } catch (Exception e) { + // Handle any exceptions that may occur + return "Error retrieving system information: " + e.getMessage(); + } + } + + /** + * Bytes to gb double. + * + * @param bytesValue the bytes value + * @return the double + */ + private static double bytesToGB(final long bytesValue) { + return BigDecimal.valueOf(bytesValue / (1024.0 * 1024 * 1024)).setScale(2, RoundingMode.HALF_UP).doubleValue(); + } +} From 3b9c80c568e1a1e8dbec45d21cf922705bcc9647 Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Fri, 19 Sep 2025 16:14:09 +0800 Subject: [PATCH 15/17] fix cr --- .../service/impl/InstanceCheckService.java | 7 ++-- .../service/impl/UpstreamCheckService.java | 2 +- ...stractShenyuClientRegisterServiceImpl.java | 15 ++++---- .../shenyu/common/constant/Constants.java | 25 +++++++++++++ .../common/enums/InstanceStatusEnum.java | 11 +++--- .../shenyu/common/utils/SystemInfoUtils.java | 35 ++++++++++++++----- .../shenyu-register-client-beat/pom.xml | 5 --- .../client/beat/HeartbeatListener.java | 3 +- 8 files changed, 70 insertions(+), 33 deletions(-) diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java index 933739a07b54..e5654cfbb28d 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceCheckService.java @@ -53,7 +53,7 @@ public class InstanceCheckService { private static final int MAX_HISTORY_SIZE = 20; - private static final Logger LOG = LoggerFactory.getLogger(UpstreamCheckService.class); + private static final Logger LOG = LoggerFactory.getLogger(InstanceCheckService.class); private ScheduledThreadPoolExecutor executor; @@ -83,7 +83,7 @@ public InstanceCheckService(final InstanceInfoService instanceInfoService) { */ public void setup() { this.fetchInstanceData(); - executor = new ScheduledThreadPoolExecutor(1, ShenyuThreadFactory.create("scheduled-instance-task", false)); + executor = new ScheduledThreadPoolExecutor(1, ShenyuThreadFactory.create("scheduled-instance-heartbeat-task", false)); executor.scheduleWithFixedDelay(this::scheduled, 30, scheduledTime, TimeUnit.SECONDS); executor.scheduleWithFixedDelay(this::syncDB, 40, scheduledTime, TimeUnit.SECONDS); } @@ -138,7 +138,7 @@ private void scheduled() { try { doCheck(); } catch (Exception e) { - LOG.error("upstream scheduled check error -------- ", e); + LOG.error("upstream scheduled check error", e); } } @@ -178,6 +178,7 @@ public void syncDB() { @PreDestroy public void close() { syncDB(); + instanceHealthBeatInfo.clear(); executor.shutdown(); } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/UpstreamCheckService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/UpstreamCheckService.java index a370be0a906e..5e559ebddd71 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/UpstreamCheckService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/UpstreamCheckService.java @@ -279,7 +279,7 @@ private void scheduled() { doCheck(); waitFinish(); } catch (Exception e) { - LOG.error("upstream scheduled check error -------- ", e); + LOG.error("upstream scheduled check error", e); } } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImpl.java index c65c3b28dff4..165f4abb9e6d 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImpl.java @@ -257,15 +257,14 @@ public String doHeartbeat(final String selectorName, final List try { // publish instance info event - publisher.publish( - new InstanceInfoReportEvent( - uriRegisterDTO.getHost(), - String.valueOf(uriRegisterDTO.getPort()), - InstanceTypeConstants.CLIENT_INSTANCE_TYPE, - uriRegisterDTO.getInstanceInfo(), - uriRegisterDTO.getNamespaceId() - ) + InstanceInfoReportEvent instanceInfoReportEvent = new InstanceInfoReportEvent( + uriRegisterDTO.getHost(), + String.valueOf(uriRegisterDTO.getPort()), + InstanceTypeConstants.CLIENT_INSTANCE_TYPE, + uriRegisterDTO.getInstanceInfo(), + uriRegisterDTO.getNamespaceId() ); + publisher.publish(instanceInfoReportEvent); } catch (Exception e) { LOG.error("publish instance info error", e); } diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java index 3be46f974045..6fa7e39ccda0 100644 --- a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java +++ b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java @@ -1029,6 +1029,31 @@ public interface Constants { * The constant AI_MODEL. */ String AI_MODEL = "ai_model"; + + /** + * The constant arch. + */ + String ARCH="arch"; + + /** + * The constant arch. + */ + String OPERATING_SYSTEM="operatingSystem"; + + /** + * The constant availableProcessors. + */ + String AVAILABLE_PROCESSORS="availableProcessors"; + + /** + * The constant totalMemorySizeGB. + */ + String TOTAL_MEMORY_SIZE_GB="totalMemorySizeGB"; + + /** + * The constant GB. + */ + String GB="GB"; /** * String q. diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/InstanceStatusEnum.java b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/InstanceStatusEnum.java index 2d01afa579af..bba3fb5ac818 100644 --- a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/InstanceStatusEnum.java +++ b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/InstanceStatusEnum.java @@ -20,19 +20,18 @@ public enum InstanceStatusEnum { /** - * OFFLINE. + * DELETED. */ - OFFLINE(2, "OFFLINE"), - + DELETED(0, "DELETED"), /** * ONLINE. */ ONLINE(1, "ONLINE"), /** - * DELETED. + * OFFLINE. */ - DELETED(0, "DELETED"); + OFFLINE(2, "OFFLINE"); private final int code; @@ -57,6 +56,6 @@ public static String getNameByCode(final int code) { return status.getName(); } } - return "UNKNOWN"; + return DELETED.name; } } diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java index b137abc440a9..0dd4842867ea 100644 --- a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java +++ b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java @@ -18,6 +18,7 @@ package org.apache.shenyu.common.utils; import com.sun.management.OperatingSystemMXBean; +import org.apache.shenyu.common.exception.ShenyuException; import oshi.SystemInfo; import java.lang.management.ManagementFactory; @@ -25,11 +26,27 @@ import java.math.RoundingMode; import java.util.Map; +import static org.apache.shenyu.common.constant.Constants.ARCH; +import static org.apache.shenyu.common.constant.Constants.AVAILABLE_PROCESSORS; +import static org.apache.shenyu.common.constant.Constants.GB; +import static org.apache.shenyu.common.constant.Constants.OPERATING_SYSTEM; +import static org.apache.shenyu.common.constant.Constants.TOTAL_MEMORY_SIZE_GB; + /** * The type System info utils. */ public final class SystemInfoUtils { - + + private static final int BYTES_IN_KB = 1024; + + private static final int BYTES_IN_MB = BYTES_IN_KB * 1024; + + private static final int BYTES_IN_GB = BYTES_IN_MB * 1024; + + private static final int DECIMAL_PLACES = 2; + + private static final RoundingMode ROUNDING_MODE = RoundingMode.HALF_UP; + /** * Gets system info. * @@ -44,15 +61,15 @@ public static String getSystemInfo() { OperatingSystemMXBean osBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); Map hostInfo = Map.of( - "arch", osBean.getArch(), - "operatingSystem", systemInfo.getOperatingSystem().toString(), - "availableProcessors", osBean.getAvailableProcessors(), - "totalMemorySizeGB", bytesToGB(osBean.getTotalMemorySize()) + " GB" + ARCH, osBean.getArch(), + OPERATING_SYSTEM, systemInfo.getOperatingSystem().toString(), + AVAILABLE_PROCESSORS, osBean.getAvailableProcessors(), + TOTAL_MEMORY_SIZE_GB, bytesToGB(osBean.getTotalMemorySize()) + GB ); return GsonUtils.getInstance().toJson(hostInfo); } catch (Exception e) { // Handle any exceptions that may occur - return "Error retrieving system information: " + e.getMessage(); + throw new ShenyuException("Error retrieving system information: " + e.getMessage()); } } @@ -63,6 +80,8 @@ public static String getSystemInfo() { * @return the double */ private static double bytesToGB(final long bytesValue) { - return BigDecimal.valueOf(bytesValue / (1024.0 * 1024 * 1024)).setScale(2, RoundingMode.HALF_UP).doubleValue(); - } + return BigDecimal.valueOf(bytesValue / (double) BYTES_IN_GB) + .setScale(DECIMAL_PLACES, ROUNDING_MODE) + .doubleValue(); + } } diff --git a/shenyu-register-center/shenyu-register-client-beat/pom.xml b/shenyu-register-center/shenyu-register-client-beat/pom.xml index 8e7933dd2ec0..272105abd08c 100644 --- a/shenyu-register-center/shenyu-register-client-beat/pom.xml +++ b/shenyu-register-center/shenyu-register-client-beat/pom.xml @@ -27,11 +27,6 @@ shenyu-register-client-beat - - 17 - 17 - UTF-8 - org.apache.shenyu diff --git a/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java b/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java index 662e073fd3d9..a5db7aad439e 100644 --- a/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java +++ b/shenyu-register-center/shenyu-register-client-beat/src/main/java/org/apache/shenyu/register/client/beat/HeartbeatListener.java @@ -52,10 +52,9 @@ public HeartbeatListener(final ShenyuClientRegisterRepository httpClientRegister this.httpClientRegisterRepository = httpClientRegisterRepository; this.shenyuConfig = shenyuConfig; LOG.info("Web server initialized on port {}, starting heartbeat reporter", serverProperties.getPort()); - //启动心跳任务 executor.scheduleAtFixedRate(() -> { InstanceBeatInfoDTO instanceBeatInfoDTO = new InstanceBeatInfoDTO(); - instanceBeatInfoDTO.setInstancePort(serverProperties.getPort() + ""); + instanceBeatInfoDTO.setInstancePort(String.valueOf(serverProperties.getPort())); instanceBeatInfoDTO.setInstanceIp(IpUtils.getHost()); instanceBeatInfoDTO.setNamespaceId(shenyuConfig.getNamespace()); instanceBeatInfoDTO.setInstanceInfo(SystemInfoUtils.getSystemInfo()); From 4262ec7c83990adddc748b940b82ee4eb9032443 Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Fri, 19 Sep 2025 16:14:36 +0800 Subject: [PATCH 16/17] fix cr --- shenyu-admin/src/main/resources/application-mysql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shenyu-admin/src/main/resources/application-mysql.yml b/shenyu-admin/src/main/resources/application-mysql.yml index 6db63a81d148..73c9a817a103 100755 --- a/shenyu-admin/src/main/resources/application-mysql.yml +++ b/shenyu-admin/src/main/resources/application-mysql.yml @@ -22,7 +22,7 @@ spring: datasource: url: jdbc:mysql://localhost:3306/shenyu?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true username: root - password: passwd4mysql + password: 12345678 driver-class-name: com.mysql.cj.jdbc.Driver hikari: connection-timeout: 30000 From dff69ec2e671eff11f20840cb35dd8db21fb1291 Mon Sep 17 00:00:00 2001 From: xchoox <605739993@qq.com> Date: Fri, 19 Sep 2025 17:26:22 +0800 Subject: [PATCH 17/17] fix cr --- .../shenyu/common/constant/Constants.java | 345 +++++++++--------- .../shenyu/common/utils/SystemInfoUtils.java | 6 +- 2 files changed, 175 insertions(+), 176 deletions(-) diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java index 6fa7e39ccda0..0a5b4be8d8bc 100644 --- a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java +++ b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java @@ -31,7 +31,7 @@ public interface Constants { * The constant string dot. */ String DOT = "."; - + /** * The constant string separator. */ @@ -41,238 +41,238 @@ public interface Constants { * The constant string separator. */ String SEPARATOR_UNDERLINE = "_"; - + /** * The constant SUCCESS. */ String SUCCESS = "success"; - + /** * The constant APP_PARAM. */ String APP_PARAM = "appParam"; - + /** * The constant context. */ String CONTEXT = "context"; - + /** * The constant chain. */ String CHAIN = "chain"; - + /** * The constant context path. */ String CONTEXT_PATH = "contextPath"; - + /** * The constant META_DATA. */ String META_DATA = "metaData"; - + /** * The constant OLD_CONTEXT_PATH_META_DATA. */ String OLD_CONTEXT_PATH_META_DATA = "old_context_path_meta_data"; - + /** * The constant OLD_META_DATA. */ String OLD_META_DATA = "old_meta_data"; - + /** * The constant CLIENT_RESPONSE_ATTR. */ String CLIENT_RESPONSE_ATTR = "webHandlerClientResponse"; - + /** * The constant DUBBO_RPC_RESULT_EMPTY. */ String DUBBO_RPC_RESULT_EMPTY = "dubbo has not return value!"; - + /** * The constant SOFA_RPC_RESULT_EMPTY. */ String SOFA_RPC_RESULT_EMPTY = "sofa has not return value!"; - + /** * The constant RPC_RESULT. */ String RPC_RESULT = "rpc_result"; - + /** * The constant MOTAN_RPC_RESULT. */ String MOTAN_RPC_RESULT = "motan_rpc_result"; - + /** * The constant TARS_RPC_RESULT_EMPTY. */ String TARS_RPC_RESULT_EMPTY = "tars has not return value!"; - + /** * The constant MOTAN_RPC_RESULT_EMPTY. */ String MOTAN_RPC_RESULT_EMPTY = "motan has not return value!"; - + /** * The constant CLIENT_RESPONSE_RESULT_TYPE. */ String CLIENT_RESPONSE_RESULT_TYPE = "webHandlerClientResponseResultType"; - + /** * The constant CLIENT_RESPONSE_CONN_ATTR. */ String CLIENT_RESPONSE_CONN_ATTR = "nettyClientResponseConnection"; - + /** * The constant HTTP_TIME_OUT. */ String HTTP_TIME_OUT = "httpTimeOut"; - + /** * The constant HTTP_RETRY. */ String HTTP_RETRY = "httpRetry"; - + /** * The constant RETRY_STRATEGY. */ String RETRY_STRATEGY = "retryStrategy"; - + /** * The constant LOAD_BALANCE. */ String LOAD_BALANCE = "loadBalance"; - + /** * divide online selector id. */ String DIVIDE_SELECTOR_ID = "divideSelectorId"; - + /** * Original response Content-Type attribute name. */ String ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR = "original_response_content_type"; - + /** * The constant HTTP_URI. */ String HTTP_URI = "httpUri"; - + /** * The constant HTTP_DOMAIN. */ String HTTP_DOMAIN = "httpDomain"; - + /** * The constant RPC_PARAM_TRANSFORM. */ String PARAM_TRANSFORM = "param_transform"; - + /** * The constant DECODE. */ String DECODE = "UTF-8"; - + /** * The constant MODULE. */ String MODULE = "module"; - + /** * RESPONSE_MONO. */ String RESPONSE_MONO = "RESPONSE_MONO"; - + /** * WATCHER_HTTP_STATUS. */ String WATCHER_HTTP_STATUS = "WATCHER_HTTP_STATUS"; - + /** * The constant METHOD. */ String METHOD = "method"; - + /** * The constant APP_KEY. */ String APP_KEY = "appKey"; - + /** * The constant RPC_TYPE. */ String RPC_TYPE = "rpcType"; - + /** * The constant SIGN. */ String SIGN = "sign"; - + /** * The constant PATH. */ String PATH = "path"; - + /** * The constant VERSION. */ String VERSION = "version"; - + /** * The constant SIGN_PARAMS_ERROR. */ String SIGN_PARAMS_ERROR = "sign parameters are incomplete!"; - + /** * The constant SIGN_VERSION_ERROR. */ String SIGN_VERSION_ERROR = "sign version does not exist or is wrong!"; - + /** * The constant SIGN_APP_KEY_IS_NOT_EXIST. */ String SIGN_APP_KEY_IS_NOT_EXIST = "sign appKey does not exist."; - + /** * The constant SIGN_PATH_NOT_EXIST. */ String SIGN_PATH_NOT_EXIST = "you have not configured the sign path."; - + /** * The constant SIGN_VALUE_IS_ERROR. */ String SIGN_VALUE_IS_ERROR = "signature value is error!"; - + /** * The constant TIMESTAMP. */ String TIMESTAMP = "timestamp"; - + /** * The constant REJECT_MSG. */ String REJECT_MSG = " You are forbidden to visit"; - + /** * The constant REWRITE_URI. */ String REWRITE_URI = "rewrite_uri"; - + /** * The constant REWRITE_CONTEXT_PATH. */ String REWRITE_CONTEXT_PATH = "rewrite_context_path"; - + /** * The constant URI. */ String URI = "uri"; - + /** * The constant HEARTBEAT. */ @@ -287,164 +287,164 @@ public interface Constants { * The constant LINE_SEPARATOR. */ String LINE_SEPARATOR = System.lineSeparator(); - + /** * The constant URL_SEPARATOR. */ String PATH_SEPARATOR = "/"; - + /** * hystrix withExecutionIsolationSemaphoreMaxConcurrentRequests. */ int MAX_CONCURRENT_REQUESTS = 100; - + /** * hystrix withCircuitBreakerErrorThresholdPercentage. */ int ERROR_THRESHOLD_PERCENTAGE = 50; - + /** * hystrix withCircuitBreakerRequestVolumeThreshold. */ int REQUEST_VOLUME_THRESHOLD = 20; - + /** * hystrix withCircuitBreakerSleepWindowInMilliseconds. */ int SLEEP_WINDOW_INMILLISECONDS = 5000; - + /** * The constant TIME_OUT. */ long TIME_OUT = 3000; - + /** * The constant COLONS. */ String COLONS = ":"; - + /** * hystrix thead pool core size. */ int HYSTRIX_THREAD_POOL_CORE_SIZE = 10; - + /** * hystrix thread pool max size. */ int HYSTRIX_THREAD_POOL_MAX_SIZE = 10; - + /** * hystrix thread pool keep alive time minutes. */ int HYSTRIX_THREAD_KEEP_ALIVE_TIME_MINUTE = 1; - + /** * hystrix thread pool queue size. */ int HYSTRIX_THREAD_POOL_QUEUE_SIZE = 12; - + /** * ratelimiter timeoutDurationRate. */ int TIMEOUT_DURATION_RATE = 5000; - + /** * ratelimiter limitRefreshPeriod. */ int LIMIT_REFRESH_PERIOD = 500; - + /** * ratelimiter limitForPeriod. */ int LIMIT_FOR_PERIOD = 50; - + /** * circuitBreaker circuitEnable. */ int CIRCUIT_DISABLE = 0; - + /** * circuitBreaker enable. */ int CIRCUIT_ENABLE = 1; - + /** * circuitBreaker timeoutDuration. */ long TIMEOUT_DURATION = 30000; - + /** * circuitBreaker slidingWindowSize. */ int SLIDING_WINDOW_SIZE = 100; - + /** * circuitBreaker slidingWindowType. */ int SLIDING_WINDOW_TYPE = 0; - + /** * circuitBreaker minimumNumberOfCalls. */ int MINIMUM_NUMBER_OF_CALLS = 100; - + /** * circuitBreaker waitIntervalFunctionInOpenState. */ int WAIT_INTERVAL_FUNCTION_IN_OPEN_STATE = 60000; - + /** * circuitBreaker waitIntervalFunctionInOpenState. */ int PERMITTED_NUMBER_OF_CALLS_IN_HALF_OPEN_STATE = 10; - + /** * circuitBreaker failureRateThreshold. */ float FAILURE_RATE_THRESHOLD = 50; - + /** * circuitBreaker automaticTransitionFromOpenToHalfOpenEnabled. */ boolean AUTOMATIC_TRANSITION_FROM_OPEN_TO_HALF_OPEN_ENABLED = false; - + /** * jwt handle key for secretKey. */ String SECRET_KEY = "secretKey"; - + /** * basicAuth handle key for defaultHandleJson. */ String DEFAULT_HANDLE_JSON = "defaultHandleJson"; - + /** * local key. */ String LOCAL_KEY = "localKey"; - + /** * jwt handle key for filterPath. */ String FILTER_PATH = "filterPath"; - + /** - * Disable flow control rules. + * Disable flow control rules. */ int FLOW_RULE_ENABLE_OFF = 0; /** - * Enable flow control rules. + * Enable flow control rules. */ int FLOW_RULE_ENABLE_ON = 1; /** - * Disable flow degrade rules. + * Disable flow degrade rules. */ int DEGRADE_RULE_ENABLE_OFF = 0; /** - * Enable flow degrade rules. + * Enable flow degrade rules. */ int DEGRADE_RULE_ENABLE_ON = 1; @@ -452,122 +452,122 @@ public interface Constants { * Enable the flow rule. */ int SENTINEL_ENABLE_FLOW_RULE = 1; - + /** * Sentinel qps flow grade. */ int SENTINEL_QPS_FLOW_GRADE = 1; - + /** * Sentinel flow reject behavior. */ int SENTINEL_FLOW_REJECT = 0; - + /** * Enable the degrade rule. */ int SENTINEL_ENABLE_DEGRADE_RULE = 1; - + /** * Sentinel response RT degrade rule. */ int SENTINEL_RESPONSE_RULE_GRADE = 0; - + /** * Sentinel degrade rule default min request. */ int SENTINEL_MIN_REQUEST_AMOUNT = 5; - + /** * Sentinel degrade rule default slow ratio threshold. */ double SENTINEL_SLOW_RATIO_THRESHOLD = 1.0d; - + /** * Sentinel degrade rule default stat intervals. */ int SENTINEL_STAT_INTERVALS = 1; - + /** * default warmup. */ int DEFAULT_WARMUP = 10 * 60 * 1000; - + /** * default register type. */ String DEFAULT_REGISTER_TYPE = "http"; - + /** * is checked. */ String IS_CHECKED = "checked"; - + /** * default checked value. */ String DEFAULT_CHECK_VALUE = "false"; - + /** * zombie check threads. */ String ZOMBIE_CHECK_THREADS = "zombieCheckThreads"; - + /** * default zombie check threads value. */ String ZOMBIE_CHECK_THREADS_VALUE = "10"; - + /** * zombie check times. */ String ZOMBIE_CHECK_TIMES = "zombieCheckTimes"; - + /** * default zombie check times value. */ String ZOMBIE_CHECK_TIMES_VALUE = "5"; - + /** * scheduled time. */ String SCHEDULED_TIME = "scheduledTime"; - + /** * default scheduled time value. */ String SCHEDULED_TIME_VALUE = "10"; - + /** * default headerMaxSize value. */ int HEADER_MAX_SIZE = 10240; - + /** * default requestMaxSize value. */ int REQUEST_MAX_SIZE = 102400; - + /** * String default. */ String DEFAULT = "DEFAULT"; - + /** * context path name prefix. */ String CONTEXT_PATH_NAME_PREFIX = "/context-path"; - + /** * dubbo gray release selector id. */ String DUBBO_SELECTOR_ID = "dubboSelectorId"; - + /** * dubbo gray release rule id. */ String DUBBO_RULE_ID = "dubboRuleId"; - + /** * dubbo remote address. */ @@ -587,57 +587,57 @@ public interface Constants { * dubbo default application name. */ String DUBBO_DEFAULT_APPLICATION_NAME = "shenyu_proxy"; - + /** * dubbo group. */ String GROUP = "group"; - + /** * redis script path. */ String SCRIPT_PATH = "/META-INF/scripts/"; - + /** * cache max count. */ int CACHE_MAX_COUNT = 1000; - + /** * the empty json. */ String EMPTY_JSON = "{}"; - + /** * http accept encoding gzip. */ String HTTP_ACCEPT_ENCODING_GZIP = "gzip"; - + /** * general context. */ String GENERAL_CONTEXT = "generalContext"; - + /** * addGeneralContextType. */ String ADD_GENERAL_CONTEXT_TYPE = "addGeneralContext"; - + /** * transmitHeaderToGeneralContext. */ String TRANSMIT_HEADER_TO_GENERAL_CONTEXT_TYPE = "transmitHeaderToGeneralContext"; - + /** * When register by http, the meta register path. */ String META_PATH = "/shenyu-client/register-metadata"; - + /** * When register by http, the meta type. */ String META_TYPE = "metadata"; - + /** * When register by http, the uri path. */ @@ -647,12 +647,12 @@ public interface Constants { * When register by http, the uri path. */ String BEAT_URI_PATH = "/instance/beat"; - + /** * When register by http, the offline path. */ String OFFLINE_PATH = "/shenyu-client/offline"; - + /** * The constant API_DOC_TYPE. */ @@ -682,12 +682,12 @@ public interface Constants { * When register by http, admin username. */ String USER_NAME = "username"; - + /** * Login name. */ String LOGIN_NAME = "userName"; - + /** * When register by http, admin password. */ @@ -707,87 +707,87 @@ public interface Constants { * X-Access-Token. */ String X_ACCESS_TOKEN = "X-Access-Token"; - + /** * The admin return result code. */ String ADMIN_RESULT_CODE = "code"; - + /** * The admin return result data. */ String ADMIN_RESULT_DATA = "data"; - + /** * The admin return result token. */ String ADMIN_RESULT_TOKEN = "token"; - + /** * The admin return result expired time. */ String ADMIN_RESULT_EXPIRED_TIME = "expiredTime"; - + /** * The admin userName. */ String ADMIN_RESULT_USERNAME = "userName"; - + /** * The admin password. */ String ADMIN_RESULT_PASSWORD = "password"; - + /** * shenyu admin path configs fetch. */ String SHENYU_ADMIN_PATH_CONFIGS_FETCH = "/configs/fetch"; - + /** * shenyu admin path configs listener. */ String SHENYU_ADMIN_PATH_CONFIGS_LISTENER = "/configs/listener"; - + /** * zombie removal times. */ String ZOMBIE_REMOVAL_TIMES = "zombieRemovalTimes"; - + /** * The default zombie removal time value, unit is second. */ String ZOMBIE_REMOVAL_TIMES_VALUE = "60"; - + /** * shared thread pool type. */ String SHARED = "shared"; - + /** * fixed thread pool type. */ String FIXED = "fixed"; - + /** * eager thread pool type. */ String EAGER = "eager"; - + /** * limited thread pool type. */ String LIMITED = "limited"; - + /** * cached thread pool type. */ String CACHED = "cached"; - + /** * user can use the specify-domain to replace of upstream url of the divide plugin. */ String SPECIFY_DOMAIN = "specify-domain"; - + /** * The maximum free memory reserved by the blocking queue for the JVM. */ @@ -799,33 +799,32 @@ public interface Constants { * The default cluster of dubbo client. */ String DEFAULT_CLUSTER = "failover"; - + /** * cache data max size, means map size. */ Long LRU_MAP_MAXSIZE = 65536L; - + /** * namespace,sush as nacos . */ String NAMESPACE = "namespace"; - + /** * brpc spi bizThreadPoolName. */ String SHARED_BIZTHREADPOOLNAME = "shared"; - - /** + /** * trie default children size. */ Integer TRIE_CHILDREN_SIZE = 512; - + /** * trie default path variables size. */ Integer TRIE_PATH_VARIABLES_SIZE = 128; - + /** * trie default path cache size. */ @@ -835,7 +834,7 @@ public interface Constants { * the default warm time is ten minutes. */ int WARMUP_TIME = 10 * 60 * 1000; - + /** * The constant DEFAULT_RULE. */ @@ -880,82 +879,82 @@ public interface Constants { * Hystrix plugin metrics. */ String METRICS_HYSTRIX = "metricsHystrix"; - + /** * The constant shenyu namespace id. */ String SHENYU_NAMESPACE_ID = "namespaceId"; - + /** * The constant SYS_DEFAULT_NAMESPACE_ID. */ String SYS_DEFAULT_NAMESPACE_ID = "649330b6-c2d7-4edc-be8e-8a54df9eb385"; - + /** * The constant DEFAULT_NAMESPACE_PRIMARY_KEY. */ String DEFAULT_NAMESPACE_PRIMARY_KEY = "1"; - + /** * The constant EVENT_NAME_DICT. */ String EVENT_NAME_DICT = "dict"; - + /** * The constant EVENT_NAME_PLUGIN_HANDLE. */ String EVENT_NAME_PLUGIN_HANDLE = "plugin-handle"; - + /** * The constant EVENT_NAME_META_DATA. */ String EVENT_NAME_META_DATA = "meta-data"; - + /** * The constant EVENT_NAME_NAMESPACE. */ String EVENT_NAME_NAMESPACE = "namespace"; - + /** * The constant EVENT_NAME_PLUGIN. */ String EVENT_NAME_PLUGIN = "plugin"; - + /** * The constant EVENT_NAME_NAMESPACE_PLUGIN. */ String EVENT_NAME_NAMESPACE_PLUGIN = "namespace-plugin"; - + /** * The constant EVENT_NAME_RESOURCE. */ String EVENT_NAME_RESOURCE = "resource"; - + /** * The constant EVENT_NAME_ROLE. */ String EVENT_NAME_ROLE = "role"; - + /** * The constant EVENT_NAME_RULE. */ String EVENT_NAME_RULE = "rule"; - + /** * The constant EVENT_NAME_SELECTOR. */ String EVENT_NAME_SELECTOR = "selector"; - + /** * The constant EVENT_NAME_USER. */ String EVENT_NAME_USER = "user"; - + /** * The constant EVENT_NAME_DATA. */ String EVENT_NAME_DATA = "data"; - + /** * The constant EVENT_NAME_REGISTER. */ @@ -985,7 +984,7 @@ public interface Constants { * The constant messages. */ String MESSAGES = "messages"; - + /** * The constant Content-Encoding. */ @@ -999,12 +998,12 @@ public interface Constants { * The constant Content. */ String CONTENT = "content"; - + /** * The constant ROLE. */ String ROLE = "role"; - + /** * The constant USAGE. */ @@ -1019,12 +1018,12 @@ public interface Constants { * The stream_options. */ String STREAM_OPTIONS = "stream_options"; - + /** * The constant COMPLETION_TOKENS. */ String COMPLETION_TOKENS = "completion_tokens"; - + /** * The constant AI_MODEL. */ @@ -1033,32 +1032,32 @@ public interface Constants { /** * The constant arch. */ - String ARCH="arch"; + String ARCH = "arch"; /** * The constant arch. */ - String OPERATING_SYSTEM="operatingSystem"; + String OPERATING_SYSTEM = "operatingSystem"; /** * The constant availableProcessors. */ - String AVAILABLE_PROCESSORS="availableProcessors"; + String AVAILABLE_PROCESSORS = "availableProcessors"; /** * The constant totalMemorySizeGB. */ - String TOTAL_MEMORY_SIZE_GB="totalMemorySizeGB"; + String TOTAL_MEMORY_SIZE_GB = "totalMemorySizeGB"; /** * The constant GB. */ - String GB="GB"; - + String GB = "GB"; + /** * String q. */ default void findConstants() { } - + } diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java index 0dd4842867ea..828db2e52675 100644 --- a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java +++ b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java @@ -56,7 +56,7 @@ public static String getSystemInfo() { try { // Get host information using OSHI SystemInfo systemInfo = new SystemInfo(); - + // Get host information OperatingSystemMXBean osBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); @@ -72,7 +72,7 @@ TOTAL_MEMORY_SIZE_GB, bytesToGB(osBean.getTotalMemorySize()) + GB throw new ShenyuException("Error retrieving system information: " + e.getMessage()); } } - + /** * Bytes to gb double. * @@ -83,5 +83,5 @@ private static double bytesToGB(final long bytesValue) { return BigDecimal.valueOf(bytesValue / (double) BYTES_IN_GB) .setScale(DECIMAL_PLACES, ROUNDING_MODE) .doubleValue(); - } + } }