5 Комити 3ae2e0895c ... aa658183d9

Аутор SHA1 Порука Датум
  reghao aa658183d9 调整 mgr 中 PipelineContext 的日志, 不输出到控制台 пре 2 дана
  reghao b6b7e62555 调整 agent 的配置 пре 2 дана
  reghao f7b5741405 设置 websocket 默认 buffer 为 64 KiB пре 2 дана
  reghao c70c127865 将构建日志文件的内容格式化为 html 后返回到前端 пре 2 дана
  reghao 9f58de5470 更新 mgr 和 agent 的脚本 пре 2 дана

+ 0 - 26
agent/src/main/java/cn/reghao/devops/agent/AgentApp.java

@@ -6,20 +6,14 @@ import ch.qos.logback.classic.LoggerContext;
 import cn.reghao.devops.agent.config.ConfigFile;
 import cn.reghao.devops.agent.config.AgentConfig;
 import cn.reghao.devops.agent.ws.WebSocketClient;
-import cn.reghao.devops.common.docker.Docker;
-import cn.reghao.devops.common.docker.DockerImpl;
 import cn.reghao.devops.common.docker.DockerManager;
 import cn.reghao.jutil.jdk.serializer.JsonConverter;
-import cn.reghao.jutil.jdk.string.StringRegexp;
-import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
 import lombok.extern.slf4j.Slf4j;
 import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.io.IOException;
 import java.net.*;
-import java.nio.charset.StandardCharsets;
-import java.util.concurrent.ScheduledExecutorService;
 
 @Slf4j
 public class AgentApp {
@@ -29,25 +23,6 @@ public class AgentApp {
 		rootLogger.setLevel(Level.INFO);
 	}
 
-	private static void tryConnect(String host, int port) {
-		try {
-			boolean isAddress = StringRegexp.matchIPv4Address(host);
-			InetAddress inetAddress;
-			if (isAddress) {
-				inetAddress = InetAddress.getByAddress(host.getBytes(StandardCharsets.UTF_8));
-			} else {
-				inetAddress = InetAddress.getByName(host);
-			}
-
-			InetSocketAddress socketAddress = new InetSocketAddress(inetAddress, port);
-			Socket socket = new Socket();
-			socket.connect(socketAddress);
-		} catch (IOException e) {
-			String errorMsg = String.format("尝试建立到 %s:%s 的 Socket 连接失败", host, port);
-			throw  new RuntimeException(errorMsg);
-		}
-	}
-
 	private static void shutdownGracefully(WebSocketClient webSocketClient) {
 		Runtime.getRuntime().addShutdownHook(new Thread(() -> {
 			log.info("收到退出信号,正在执行清理...");
@@ -114,7 +89,6 @@ public class AgentApp {
 			AgentConfig agentConfig = JsonConverter.jsonFileToObject(new File(configFilePath), AgentConfig.class);
 			// 4. 启动核心服务 (心跳、监控、WebSocket)
 			WebSocketClient webSocketClient = new WebSocketClient(agentConfig);
-			tryConnect(agentConfig.getHost(), agentConfig.getPort());
 			webSocketClient.start();
 			shutdownGracefully(webSocketClient);
 			// 6. 阻塞主线程,防止应用退出

+ 0 - 7
agent/src/main/java/cn/reghao/devops/agent/config/AgentConfig.java

@@ -1,6 +1,5 @@
 package cn.reghao.devops.agent.config;
 
-import cn.reghao.devops.common.util.Machine;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.Setter;
@@ -15,17 +14,11 @@ import java.util.UUID;
 @Setter
 @Getter
 public class AgentConfig {
-    private String agentId;
-    private String host;
-    private int port;
     private String serverUrl;
-    private String dockerHost;
     private String token;
 
     public AgentConfig() {
-        this.agentId = Machine.ID;
         this.serverUrl = "ws://localhost:4030";
-        this.dockerHost = "unix:///var/run/docker.sock";
         this.token = UUID.randomUUID().toString();
     }
 }

+ 1 - 2
bin/agent/devopsagent.json

@@ -1,4 +1,3 @@
 {
-  "host": "127.0.0.1",
-  "port": 4030
+  "serverUrl": "ws://localhost:4030"
 }

+ 7 - 1
bin/agent/start.sh

@@ -2,4 +2,10 @@
 
 app_dir=`pwd`
 app_name='devops-agent.jar'
-java -jar ${app_dir}"/"${app_name} ${app_dir}/devopsagent.json > console.log 2>&1 &
+# -Xmx128m: 对于一个只做转发和监控的 Agent,128MB 已经绰绰有余
+#
+# -XX:+UseSerialGC: 关键点!在低内存(<2GB)环境下,使用 串行垃圾回收器 比 G1 或 Parallel 更节省内存占用(Footprint),因为它不需要维护复杂的内存分代数据结构
+java -Xms64m -Xmx128m \
+     -XX:+UseSerialGC \
+     -XX:MaxMetaspaceSize=64m \
+     -jar ${app_dir}"/"${app_name} ${app_dir}/devopsagent.json > console.log 2>&1 &

+ 2 - 1
bin/mgr/start.sh

@@ -6,6 +6,7 @@ app_name='devops-mgr.jar'
 # 使用 mvn clean package -Dmaven.test.skip -Ptest 生成 jar
 # 运行时加载 application.yml 和 devopsmgr.yml 两个配置文件, 分别位于 classpath 和文件系统路径
 # 外部指定的 devopsmgr.yml 文件会覆盖 resources/application-test.yml 文件
-java -jar ${app_dir}"/"${app_name} \
+# 限制最大堆为 4G,初始为 2G,使用 G1 垃圾回收器
+java -Xms2g -Xmx4g -XX:+UseG1GC -jar ${app_dir}"/"${app_name} \
 --spring.config.location=classpath:/application.yml,file:${app_dir}/devopsmgr.yml \
 > console.log 2>&1 &

+ 0 - 5
bin/mgr/start1.sh

@@ -1,5 +0,0 @@
-#!/bin/bash
-
-app_dir=`pwd`
-app_name='devops-mgr.jar'
-java -jar ${app_dir}"/"${app_name} > console.log 2>&1 &

+ 2 - 7
mgr/src/main/java/cn/reghao/devops/mgr/MgrApplication.java

@@ -4,15 +4,10 @@ import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 
 @SpringBootApplication
-/*@ComponentScan(basePackages = {"cn.reghao.devops.mgr"}
-        ,excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = {
-                "cn.reghao.devops.mgr.console.*"
-        })
-)*/
 public class MgrApplication {
     public static void main(String[] args) {
-        // 设置 websocket 默认 buffer 字节大小(1 MB)
-        System.setProperty("org.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE", "1024000");
+        // 设置 websocket 默认 buffer 字节大小(64 KiB)
+        System.setProperty("org.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE", "65536");
         SpringApplication.run(MgrApplication.class, args);
     }
 }

+ 24 - 1
mgr/src/main/java/cn/reghao/devops/mgr/ops/app/db/query/impl/AppBuildQueryImpl.java

@@ -197,6 +197,29 @@ public class AppBuildQueryImpl implements AppBuildQuery {
         BuildLog buildLog = buildLogRepository.findByBuildLogId(buildLogId);
         String logPath = buildLog.getLogPath();
         String logContent = textFile.readFile(logPath);
-        return logContent;
+        return ansiToHtml(logContent);
+    }
+
+    /**
+     * 将包含 ANSI 颜色代码的原始日志转换为带有 HTML span 标签的文本
+     */
+    private String ansiToHtml(String rawLog) {
+        if (rawLog == null) return "";
+
+        // 简单的 HTML 转义,防止 XSS
+        String html = rawLog.replace("&", "&amp;")
+                .replace("<", "&lt;")
+                .replace(">", "&gt;");
+
+        // 替换常见的 ANSI 颜色代码
+        // [31m -> Red, [32m -> Green, [33m -> Yellow, [36m -> Cyan, [0m -> Reset
+        html = html.replaceAll("\\u001b\\[31m", "<span style='color: #F56C6C;'>") // Red
+                .replaceAll("\\u001b\\[32m", "<span style='color: #67C23A;'>") // Green
+                .replaceAll("\\u001b\\[33m", "<span style='color: #E6A23C;'>") // Yellow
+                .replaceAll("\\u001b\\[36m", "<span style='color: #409EFF;'>") // Cyan
+                .replaceAll("\\u001b\\[0m", "</span>"); // Reset
+
+        // 处理换行符
+        return html.replace("\n", "<br/>");
     }
 }

+ 4 - 3
mgr/src/main/java/cn/reghao/devops/mgr/ops/builder/service/PipelineContext.java

@@ -8,6 +8,7 @@ import cn.reghao.devops.mgr.ops.builder.tool.repo.CommitInfo;
 import cn.reghao.devops.mgr.ops.docker.model.po.DockerRegistry;
 import lombok.Getter;
 import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
 
 import java.io.BufferedWriter;
 import java.io.File;
@@ -22,6 +23,7 @@ import java.util.Queue;
  * @author reghao
  * @date 2026-02-26 15:22:24
  */
+@Slf4j
 @Setter
 @Getter
 public class PipelineContext implements AutoCloseable {
@@ -95,15 +97,14 @@ public class PipelineContext implements AutoCloseable {
                 message);
 
         // 1. 输出到控制台 (方便宿主观察)
-        System.out.println("[" + appId + "_" + buildId + "] " + message);
-
+        //log.info("[" + appId + "_" + buildId + "] " + message);
         // 2. 写入文件 (持久化)
         try {
             writer.write(formattedMsg);
             writer.newLine();
             writer.flush(); // 实时刷盘,防止崩溃时丢失日志
         } catch (IOException e) {
-            System.err.println("无法写入日志文件: " + e.getMessage());
+            log.error("无法写入日志文件: {}", e.getMessage());
         }
 
         // 3. 更新内存摘要 (用于任务结束后存入 MySQL)