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