From 6e0425e7a95f886e2a6919492b4c369463883110 Mon Sep 17 00:00:00 2001
From: hengyu_laptop <1183660933@qq.com>
Date: Tue, 23 Jun 2026 16:05:52 +0800
Subject: [PATCH 1/2] [feat] collect and report instance system info in
heartbeat
---
shenyu-client-core/pom.xml | 6 ++
.../ShenyuClientURIExecutorSubscriber.java | 32 ++++---
.../client/core/dto/URIRegisterDTO.java | 89 +++++++++++-------
.../client/core/utils/SystemInfoUtils.java | 91 +++++++++++++++++++
4 files changed, 170 insertions(+), 48 deletions(-)
create mode 100644 shenyu-client-core/src/main/java/org/apache/shenyu/client/core/utils/SystemInfoUtils.java
diff --git a/shenyu-client-core/pom.xml b/shenyu-client-core/pom.xml
index 0c008e9..bbbb70b 100644
--- a/shenyu-client-core/pom.xml
+++ b/shenyu-client-core/pom.xml
@@ -113,6 +113,12 @@
org.apache.commons
commons-collections4
+
+
+ com.github.oshi
+ oshi-core
+ 6.10.0
+
diff --git a/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java b/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java
index b8e96a9..084a472 100644
--- a/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java
+++ b/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java
@@ -27,6 +27,7 @@
import org.apache.shenyu.client.core.shutdown.ShutdownHookManager;
import org.apache.shenyu.client.core.type.DataType;
import org.apache.shenyu.client.core.utils.ShenyuThreadFactory;
+import org.apache.shenyu.client.core.utils.SystemInfoUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
@@ -43,26 +44,28 @@
* The type Shenyu client uri executor subscriber.
*/
public class ShenyuClientURIExecutorSubscriber implements ExecutorTypeSubscriber {
-
- private static final Logger LOG = LoggerFactory.getLogger(ShenyuClientURIExecutorSubscriber.class);
-
+
+ private static final Logger LOG = LoggerFactory.getLogger(
+ ShenyuClientURIExecutorSubscriber.class);
+
private static final List URIS = Lists.newArrayList();
-
+
private final ShenyuClientRegisterRepository shenyuClientRegisterRepository;
-
+
private final ScheduledThreadPoolExecutor executor;
-
+
/**
* Instantiates a new Shenyu client uri executor subscriber.
*
* @param shenyuClientRegisterRepository the shenyu client register repository
*/
- public ShenyuClientURIExecutorSubscriber(final ShenyuClientRegisterRepository shenyuClientRegisterRepository) {
+ public ShenyuClientURIExecutorSubscriber(
+ final ShenyuClientRegisterRepository shenyuClientRegisterRepository) {
this.shenyuClientRegisterRepository = shenyuClientRegisterRepository;
// executor for send heartbeat
ThreadFactory requestFactory = ShenyuThreadFactory.create("heartbeat-reporter", true);
executor = new ScheduledThreadPoolExecutor(1, requestFactory);
-
+
executor.scheduleAtFixedRate(() -> {
try {
URIS.forEach(this::sendHeartbeat);
@@ -71,12 +74,12 @@ public ShenyuClientURIExecutorSubscriber(final ShenyuClientRegisterRepository sh
}
}, 30, 30, TimeUnit.SECONDS);
}
-
+
@Override
public DataType getType() {
return DataType.URI;
}
-
+
@Override
public void executor(final Collection dataList) {
for (URIRegisterDTO uriRegisterDTO : dataList) {
@@ -104,15 +107,15 @@ public void executor(final Collection dataList) {
}
ShenyuClientShutdownHook.delayOtherHooks();
shenyuClientRegisterRepository.persistURI(uriRegisterDTO);
-
+
URIS.add(uriRegisterDTO);
-
+
ShutdownHookManager.get().addShutdownHook(new Thread(() -> {
final URIRegisterDTO offlineDTO = new URIRegisterDTO();
BeanUtils.copyProperties(uriRegisterDTO, offlineDTO);
offlineDTO.setEventType(EventType.OFFLINE);
shenyuClientRegisterRepository.offline(offlineDTO);
-
+
// shutdown heartbeat executor
if (!executor.isTerminated()) {
executor.shutdown();
@@ -120,8 +123,9 @@ public void executor(final Collection dataList) {
}), 2);
}
}
-
+
private void sendHeartbeat(final URIRegisterDTO uriRegisterDTO) {
+ uriRegisterDTO.setInstanceInfo(SystemInfoUtils.getSystemInfo());
shenyuClientRegisterRepository.sendHeartbeat(uriRegisterDTO);
}
}
diff --git a/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/dto/URIRegisterDTO.java b/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/dto/URIRegisterDTO.java
index 5c6f05c..3b09b2b 100644
--- a/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/dto/URIRegisterDTO.java
+++ b/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/dto/URIRegisterDTO.java
@@ -28,7 +28,7 @@
* The type URI register dto.
*/
public class URIRegisterDTO implements DataTypeParent {
-
+
private String protocol;
private String appName;
@@ -42,9 +42,11 @@ public class URIRegisterDTO implements DataTypeParent {
private Integer port;
private EventType eventType;
-
+
private String namespaceId;
-
+
+ private String instanceInfo;
+
/**
* Instantiates a new Uri register dto.
*
@@ -59,7 +61,7 @@ public class URIRegisterDTO implements DataTypeParent {
*/
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;
@@ -68,8 +70,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.
*/
@@ -85,8 +88,9 @@ private URIRegisterDTO(final Builder builder) {
port = builder.port;
eventType = builder.eventType;
namespaceId = builder.namespaceId;
+ instanceInfo = builder.instanceInfo;
}
-
+
/**
* Trans form uri register dto.
*
@@ -101,7 +105,7 @@ public static URIRegisterDTO transForm(final MetaDataRegisterDTO metaDataRegiste
.host(metaDataRegisterDTO.getHost())
.port(metaDataRegisterDTO.getPort()).build();
}
-
+
/**
* return builder.
*
@@ -120,7 +124,7 @@ public static Builder builder() {
public DataType getType() {
return DataType.URI;
}
-
+
/**
* Gets protocol.
*
@@ -129,7 +133,7 @@ public DataType getType() {
public String getProtocol() {
return protocol;
}
-
+
/**
* Sets protocol.
*
@@ -138,7 +142,7 @@ public String getProtocol() {
public void setProtocol(final String protocol) {
this.protocol = protocol;
}
-
+
/**
* getAppName.
*
@@ -147,7 +151,7 @@ public void setProtocol(final String protocol) {
public String getAppName() {
return appName;
}
-
+
/**
* setAppName.
*
@@ -156,7 +160,7 @@ public String getAppName() {
public void setAppName(final String appName) {
this.appName = appName;
}
-
+
/**
* getContextPath.
*
@@ -165,7 +169,7 @@ public void setAppName(final String appName) {
public String getContextPath() {
return contextPath;
}
-
+
/**
* setContextPath.
*
@@ -174,7 +178,7 @@ public String getContextPath() {
public void setContextPath(final String contextPath) {
this.contextPath = contextPath;
}
-
+
/**
* getRpcType.
*
@@ -183,7 +187,7 @@ public void setContextPath(final String contextPath) {
public String getRpcType() {
return rpcType;
}
-
+
/**
* setRpcType.
*
@@ -192,7 +196,7 @@ public String getRpcType() {
public void setRpcType(final String rpcType) {
this.rpcType = rpcType;
}
-
+
/**
* getHost.
*
@@ -201,7 +205,7 @@ public void setRpcType(final String rpcType) {
public String getHost() {
return host;
}
-
+
/**
* setHost.
*
@@ -210,7 +214,7 @@ public String getHost() {
public void setHost(final String host) {
this.host = host;
}
-
+
/**
* getPort.
*
@@ -219,7 +223,7 @@ public void setHost(final String host) {
public Integer getPort() {
return port;
}
-
+
/**
* setPort.
*
@@ -228,7 +232,7 @@ public Integer getPort() {
public void setPort(final Integer port) {
this.port = port;
}
-
+
/**
* getEventType.
*
@@ -237,7 +241,7 @@ public void setPort(final Integer port) {
public EventType getEventType() {
return eventType;
}
-
+
/**
* getNamespaceId.
*
@@ -246,7 +250,7 @@ public EventType getEventType() {
public String getNamespaceId() {
return namespaceId;
}
-
+
/**
* setNamespaceId.
*
@@ -255,7 +259,7 @@ public String getNamespaceId() {
public void setNamespaceId(final String namespaceId) {
this.namespaceId = namespaceId;
}
-
+
/**
* setEventType.
*
@@ -265,7 +269,15 @@ public void setEventType(final EventType eventType) {
this.eventType = eventType;
}
- @Override
+ public void setInstanceInfo(String instanceInfo) {
+ this.instanceInfo = instanceInfo;
+ }
+
+ public String getInstanceInfo() {
+ return instanceInfo;
+ }
+
+ @Override
public boolean equals(final Object o) {
if (this == o) {
return Boolean.TRUE;
@@ -315,6 +327,8 @@ public String toString() {
+ eventType
+ ", namespaceId="
+ namespaceId
+ + ", instanceInfo="
+ + instanceInfo
+ '}';
}
@@ -322,7 +336,7 @@ public String toString() {
* The type Builder.
*/
public static final class Builder {
-
+
private String protocol;
private String appName;
@@ -336,12 +350,14 @@ public static final class Builder {
private Integer port;
private EventType eventType;
-
+
private String namespaceId;
+ private String instanceInfo;
+
private Builder() {
}
-
+
/**
* protocol.
*
@@ -352,7 +368,7 @@ public Builder protocol(final String protocol) {
this.protocol = protocol;
return this;
}
-
+
/**
* appName.
*
@@ -363,7 +379,7 @@ public Builder appName(final String appName) {
this.appName = appName;
return this;
}
-
+
/**
* contextPath.
*
@@ -374,7 +390,7 @@ public Builder contextPath(final String contextPath) {
this.contextPath = contextPath;
return this;
}
-
+
/**
* rpcType.
*
@@ -385,7 +401,7 @@ public Builder rpcType(final String rpcType) {
this.rpcType = rpcType;
return this;
}
-
+
/**
* host.
*
@@ -396,7 +412,7 @@ public Builder host(final String host) {
this.host = host;
return this;
}
-
+
/**
* port.
*
@@ -407,7 +423,7 @@ public Builder port(final Integer port) {
this.port = port;
return this;
}
-
+
/**
* eventType.
*
@@ -418,7 +434,7 @@ public Builder eventType(final EventType eventType) {
this.eventType = eventType;
return this;
}
-
+
/**
* namespace.
*
@@ -430,6 +446,11 @@ public Builder namespaceId(final String namespaceId) {
return this;
}
+ public Builder instanceInfo(final String instanceInfo) {
+ this.instanceInfo = instanceInfo;
+ return this;
+ }
+
/**
* build.
*
diff --git a/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/utils/SystemInfoUtils.java b/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/utils/SystemInfoUtils.java
new file mode 100644
index 0000000..b3ab342
--- /dev/null
+++ b/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/utils/SystemInfoUtils.java
@@ -0,0 +1,91 @@
+/*
+ * 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.client.core.utils;
+
+
+import com.sun.management.OperatingSystemMXBean;
+import java.lang.management.ManagementFactory;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.HashMap;
+import java.util.Map;
+import oshi.SystemInfo;
+
+/**
+ * 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;
+
+ private static final String AVAILABLE_PROCESSORS = "availableProcessors";
+
+ private static final String TOTAL_MEMORY_SIZE_GB = "totalMemorySizeGB";
+
+ private static final String GB = "GB";
+
+ private static final String ARCH = "arch";
+
+ private static final String OPERATING_SYSTEM = "operatingSystem";
+
+ /**
+ * 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();
+ long totalMemory = systemInfo.getHardware().getMemory().getTotal();
+
+ Map hostInfo = new HashMap<>();
+ hostInfo.put(ARCH, osBean.getArch());
+ hostInfo.put(OPERATING_SYSTEM, systemInfo.getOperatingSystem().toString());
+ hostInfo.put(AVAILABLE_PROCESSORS, osBean.getAvailableProcessors());
+ hostInfo.put(TOTAL_MEMORY_SIZE_GB, bytesToGB(totalMemory) + GB);
+ return GsonUtils.getInstance().toJson(hostInfo);
+ } catch (Exception e) {
+ throw new RuntimeException("Error retrieving system information: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Bytes to gb double.
+ *
+ * @param bytesValue the bytes value
+ * @return the double
+ */
+ private static double bytesToGB(final long bytesValue) {
+ return BigDecimal.valueOf(bytesValue / (double) BYTES_IN_GB)
+ .setScale(DECIMAL_PLACES, ROUNDING_MODE)
+ .doubleValue();
+ }
+}
From 1fcd9f12eddec511ccfc45f7d7c2d1c163ed20f9 Mon Sep 17 00:00:00 2001
From: hengyu_laptop <1183660933@qq.com>
Date: Tue, 23 Jun 2026 16:24:57 +0800
Subject: [PATCH 2/2] fix: fix checkStyle error
---
.../client/core/dto/URIRegisterDTO.java | 10 +-
.../client/core/utils/SystemInfoUtils.java | 91 +++++++++----------
2 files changed, 50 insertions(+), 51 deletions(-)
diff --git a/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/dto/URIRegisterDTO.java b/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/dto/URIRegisterDTO.java
index 3b09b2b..8863dac 100644
--- a/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/dto/URIRegisterDTO.java
+++ b/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/dto/URIRegisterDTO.java
@@ -269,15 +269,15 @@ public void setEventType(final EventType eventType) {
this.eventType = eventType;
}
- public void setInstanceInfo(String instanceInfo) {
- this.instanceInfo = instanceInfo;
+ public void setInstanceInfo(final String instanceInfo) {
+ this.instanceInfo = instanceInfo;
}
public String getInstanceInfo() {
return instanceInfo;
}
- @Override
+ @Override
public boolean equals(final Object o) {
if (this == o) {
return Boolean.TRUE;
@@ -447,8 +447,8 @@ public Builder namespaceId(final String namespaceId) {
}
public Builder instanceInfo(final String instanceInfo) {
- this.instanceInfo = instanceInfo;
- return this;
+ this.instanceInfo = instanceInfo;
+ return this;
}
/**
diff --git a/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/utils/SystemInfoUtils.java b/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/utils/SystemInfoUtils.java
index b3ab342..b2aa79f 100644
--- a/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/utils/SystemInfoUtils.java
+++ b/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/utils/SystemInfoUtils.java
@@ -17,7 +17,6 @@
package org.apache.shenyu.client.core.utils;
-
import com.sun.management.OperatingSystemMXBean;
import java.lang.management.ManagementFactory;
import java.math.BigDecimal;
@@ -31,61 +30,61 @@
*/
public final class SystemInfoUtils {
- private static final int BYTES_IN_KB = 1024;
+ 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_MB = BYTES_IN_KB * 1024;
+ private static final int BYTES_IN_GB = BYTES_IN_MB * 1024;
- private static final int BYTES_IN_GB = BYTES_IN_MB * 1024;
+ private static final int DECIMAL_PLACES = 2;
- private static final int DECIMAL_PLACES = 2;
+ private static final RoundingMode ROUNDING_MODE = RoundingMode.HALF_UP;
- private static final RoundingMode ROUNDING_MODE = RoundingMode.HALF_UP;
+ private static final String AVAILABLE_PROCESSORS = "availableProcessors";
- private static final String AVAILABLE_PROCESSORS = "availableProcessors";
+ private static final String TOTAL_MEMORY_SIZE_GB = "totalMemorySizeGB";
- private static final String TOTAL_MEMORY_SIZE_GB = "totalMemorySizeGB";
+ private static final String GB = "GB";
- private static final String GB = "GB";
+ private static final String ARCH = "arch";
- private static final String ARCH = "arch";
+ private static final String OPERATING_SYSTEM = "operatingSystem";
- private static final String OPERATING_SYSTEM = "operatingSystem";
+ /**
+ * Gets system info.
+ *
+ * @return the system info
+ */
+ public static String getSystemInfo() {
+ try {
+ // Get host information using OSHI
+ SystemInfo systemInfo = new SystemInfo();
- /**
- * 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();
+ long totalMemory = systemInfo.getHardware().getMemory().getTotal();
- // Get host information
- OperatingSystemMXBean osBean =
- (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
- long totalMemory = systemInfo.getHardware().getMemory().getTotal();
+ Map hostInfo = new HashMap<>();
+ hostInfo.put(ARCH, osBean.getArch());
+ hostInfo.put(OPERATING_SYSTEM, systemInfo.getOperatingSystem().toString());
+ hostInfo.put(AVAILABLE_PROCESSORS, osBean.getAvailableProcessors());
+ hostInfo.put(TOTAL_MEMORY_SIZE_GB, bytesToGB(totalMemory) + GB);
+ return GsonUtils.getInstance().toJson(hostInfo);
+ } catch (Exception e) {
+ throw new RuntimeException("Error retrieving system information: " + e.getMessage(), e);
+ }
+ }
- Map hostInfo = new HashMap<>();
- hostInfo.put(ARCH, osBean.getArch());
- hostInfo.put(OPERATING_SYSTEM, systemInfo.getOperatingSystem().toString());
- hostInfo.put(AVAILABLE_PROCESSORS, osBean.getAvailableProcessors());
- hostInfo.put(TOTAL_MEMORY_SIZE_GB, bytesToGB(totalMemory) + GB);
- return GsonUtils.getInstance().toJson(hostInfo);
- } catch (Exception e) {
- throw new RuntimeException("Error retrieving system information: " + e.getMessage(), e);
+ /**
+ * Bytes to gb double.
+ *
+ * @param bytesValue the bytes value
+ * @return the double
+ */
+ private static double bytesToGB(final long bytesValue) {
+ return BigDecimal.valueOf(bytesValue / (double) BYTES_IN_GB)
+ .setScale(DECIMAL_PLACES, ROUNDING_MODE)
+ .doubleValue();
}
- }
-
- /**
- * Bytes to gb double.
- *
- * @param bytesValue the bytes value
- * @return the double
- */
- private static double bytesToGB(final long bytesValue) {
- return BigDecimal.valueOf(bytesValue / (double) BYTES_IN_GB)
- .setScale(DECIMAL_PLACES, ROUNDING_MODE)
- .doubleValue();
- }
-}
+}
\ No newline at end of file