Merge pull request 'v1.0.2' (#6) from dev into master
Reviewed-on: #6
This commit was merged in pull request #6.
This commit is contained in:
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.imyeyu.api.modules.system.bean.DockerStatusStore;
|
||||
import com.imyeyu.api.modules.system.util.DockerEngineClient;
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.utils.Time;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -15,12 +16,13 @@ import org.springframework.scheduling.support.PeriodicTrigger;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Docker 鐘舵€侀噰闆嗕换鍔?
|
||||
* Docker 容器状态采集任务
|
||||
*
|
||||
* @author Codex
|
||||
* @since 2026-04-06
|
||||
@@ -56,20 +58,28 @@ public class DockerStatusTask implements SchedulingConfigurer {
|
||||
try {
|
||||
ArrayNode containers = (ArrayNode) dockerEngineClient.getJson("/containers/json", DockerEngineClient.query("all", "true"));
|
||||
long now = Time.now();
|
||||
synchronized (dockerStatusStore) {
|
||||
Set<String> activeIds = new HashSet<>();
|
||||
Map<String, DockerStatusStore.Container> collectedContainers = new LinkedHashMap<>();
|
||||
for (JsonNode summary : containers) {
|
||||
try {
|
||||
String containerId = getAsString(summary, "Id");
|
||||
activeIds.add(containerId);
|
||||
DockerStatusStore.Container container = dockerStatusStore.getContainers().computeIfAbsent(containerId, key -> new DockerStatusStore.Container());
|
||||
DockerStatusStore.Container container = new DockerStatusStore.Container();
|
||||
if (TimiJava.isEmpty(container)) {
|
||||
continue;
|
||||
}
|
||||
updateContainerSummary(container, summary);
|
||||
updateContainerInspect(containerId, container);
|
||||
updateContainerStats(containerId, container, now);
|
||||
collectedContainers.put(container.getId(), container);
|
||||
} catch (Exception e) {
|
||||
log.error("collect docker container item error", e);
|
||||
}
|
||||
}
|
||||
synchronized (dockerStatusStore) {
|
||||
Set<String> activeIds = new HashSet<>(collectedContainers.keySet());
|
||||
for (Map.Entry<String, DockerStatusStore.Container> item : collectedContainers.entrySet()) {
|
||||
DockerStatusStore.Container container = dockerStatusStore.getContainers().computeIfAbsent(item.getKey(), key -> new DockerStatusStore.Container());
|
||||
applyCollectedContainer(container, item.getValue());
|
||||
}
|
||||
dockerStatusStore.getContainers().entrySet().removeIf(item -> !activeIds.contains(item.getKey()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -77,6 +87,39 @@ public class DockerStatusTask implements SchedulingConfigurer {
|
||||
}
|
||||
}
|
||||
|
||||
private void applyCollectedContainer(DockerStatusStore.Container target, DockerStatusStore.Container source) {
|
||||
target.setId(source.getId());
|
||||
target.setName(source.getName());
|
||||
target.setImage(source.getImage());
|
||||
target.setImageId(source.getImageId());
|
||||
target.setCreatedAt(source.getCreatedAt());
|
||||
target.setState(source.getState());
|
||||
target.setStatus(source.getStatus());
|
||||
target.setHealthStatus(source.getHealthStatus());
|
||||
target.setStartedAt(source.getStartedAt());
|
||||
target.setFinishedAt(source.getFinishedAt());
|
||||
target.setExitCode(source.getExitCode());
|
||||
target.setRestartCount(source.getRestartCount());
|
||||
target.setOomKilled(source.isOomKilled());
|
||||
target.setCpuPercent(source.getCpuPercent());
|
||||
target.setMemoryUsageBytes(source.getMemoryUsageBytes());
|
||||
target.setMemoryLimitBytes(source.getMemoryLimitBytes());
|
||||
target.setMemoryPercent(source.getMemoryPercent());
|
||||
target.setNetworkRxBytes(source.getNetworkRxBytes());
|
||||
target.setNetworkTxBytes(source.getNetworkTxBytes());
|
||||
target.setBlockReadBytes(source.getBlockReadBytes());
|
||||
target.setBlockWriteBytes(source.getBlockWriteBytes());
|
||||
target.setPids(source.getPids());
|
||||
target.setUpdatedAt(source.getUpdatedAt());
|
||||
DockerStatusStore.Point point = source.getHistory().peekLast();
|
||||
if (point != null) {
|
||||
target.getHistory().addLast(point);
|
||||
while (historyLimit < target.getHistory().size()) {
|
||||
target.getHistory().pollFirst();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateContainerSummary(DockerStatusStore.Container container, JsonNode summary) {
|
||||
container.setId(getAsString(summary, "Id"));
|
||||
container.setName(trimContainerName(readFirstArrayText(summary, "Names")));
|
||||
@@ -108,8 +151,8 @@ public class DockerStatusTask implements SchedulingConfigurer {
|
||||
if (memoryUsageBytes != null && memoryLimitBytes != null && 0 < memoryLimitBytes) {
|
||||
memoryPercent = memoryUsageBytes * 100D / memoryLimitBytes;
|
||||
}
|
||||
Long networkRxBytes = 0L;
|
||||
Long networkTxBytes = 0L;
|
||||
long networkRxBytes = 0L;
|
||||
long networkTxBytes = 0L;
|
||||
JsonNode networks = getAsObject(stats, "networks");
|
||||
if (networks != null) {
|
||||
for (Map.Entry<String, JsonNode> item : (Iterable<Map.Entry<String, JsonNode>>) networks::fields) {
|
||||
@@ -118,8 +161,8 @@ public class DockerStatusTask implements SchedulingConfigurer {
|
||||
networkTxBytes += getAsLong(network, "tx_bytes", 0L);
|
||||
}
|
||||
}
|
||||
Long blockReadBytes = 0L;
|
||||
Long blockWriteBytes = 0L;
|
||||
long blockReadBytes = 0L;
|
||||
long blockWriteBytes = 0L;
|
||||
JsonNode blkioStats = getAsObject(stats, "blkio_stats");
|
||||
ArrayNode ioServiceBytes = blkioStats == null ? null : getAsArray(blkioStats, "io_service_bytes_recursive");
|
||||
if (ioServiceBytes != null) {
|
||||
@@ -134,7 +177,6 @@ public class DockerStatusTask implements SchedulingConfigurer {
|
||||
}
|
||||
}
|
||||
Integer pids = getNestedInteger(stats, "pids_stats", "current");
|
||||
|
||||
container.setCpuPercent(cpuPercent);
|
||||
container.setMemoryUsageBytes(memoryUsageBytes);
|
||||
container.setMemoryLimitBytes(memoryLimitBytes);
|
||||
|
||||
@@ -28,7 +28,7 @@ public class UpsStatusTask implements SchedulingConfigurer {
|
||||
private final UpsStatusClient upsStatusClient;
|
||||
private final UpsStatusStore upsStatusStore;
|
||||
|
||||
@Value("${ups.collect-enabled:true}")
|
||||
@Value("${ups.collect-enabled:false}")
|
||||
private boolean collectEnabled;
|
||||
|
||||
@Value("${ups.collect-rate-ms:60000}")
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.net.http.HttpResponse;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -73,6 +74,28 @@ public class DockerEngineClient {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断 Docker Engine 当前是否可访问。
|
||||
*
|
||||
* @return 可访问返回 true,不可访问返回 false
|
||||
*/
|
||||
public boolean isAvailable() {
|
||||
if (host.startsWith("unix://")) {
|
||||
String socketPath = host.substring("unix://".length());
|
||||
return Files.exists(Path.of(socketPath));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Docker Engine 主机配置。
|
||||
*
|
||||
* @return 主机配置字符串
|
||||
*/
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
private String buildRequestPath(String path, Map<String, String> queryParams) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("/");
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
server:
|
||||
shutdown: graceful
|
||||
# 压缩
|
||||
compression:
|
||||
enable: true
|
||||
min-response-size: 10KB
|
||||
|
||||
# 开发环境语言,激活开发配置时,多语言系统始终使用此语言环境
|
||||
dev:
|
||||
|
||||
Reference in New Issue
Block a user