|
|
/**
|
|
|
* 边车模式(Sidecar Pattern)实现
|
|
|
* 为应用提供额外的辅助功能,如日志、监控、安全等
|
|
|
*/
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
import java.util.concurrent.Executors;
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
|
public class Sidecar {
|
|
|
private final String name; // 边车名称
|
|
|
private final String appId; // 关联的应用ID
|
|
|
private final ExecutorService executor; // 执行线程池
|
|
|
private final List<SidecarFeature> features; // 边车功能列表
|
|
|
private volatile boolean running; // 运行状态
|
|
|
private final AtomicInteger requestCount = new AtomicInteger(0); // 请求计数
|
|
|
private final AtomicInteger errorCount = new AtomicInteger(0); // 错误计数
|
|
|
|
|
|
// 边车功能接口
|
|
|
public interface SidecarFeature {
|
|
|
String getName();
|
|
|
void start();
|
|
|
void stop();
|
|
|
void handleRequest(RequestContext context);
|
|
|
}
|
|
|
|
|
|
// 请求上下文
|
|
|
public static class RequestContext {
|
|
|
private final String requestId;
|
|
|
private final String path;
|
|
|
private final long startTime;
|
|
|
private long endTime;
|
|
|
private boolean success;
|
|
|
private String errorMessage;
|
|
|
|
|
|
public RequestContext(String requestId, String path) {
|
|
|
this.requestId = requestId;
|
|
|
this.path = path;
|
|
|
this.startTime = System.currentTimeMillis();
|
|
|
this.success = true;
|
|
|
}
|
|
|
|
|
|
public void complete() {
|
|
|
this.endTime = System.currentTimeMillis();
|
|
|
}
|
|
|
|
|
|
public void markError(String errorMessage) {
|
|
|
this.success = false;
|
|
|
this.errorMessage = errorMessage;
|
|
|
this.endTime = System.currentTimeMillis();
|
|
|
}
|
|
|
|
|
|
public long getDuration() {
|
|
|
return endTime - startTime;
|
|
|
}
|
|
|
|
|
|
public String getRequestId() { return requestId; }
|
|
|
public String getPath() { return path; }
|
|
|
public boolean isSuccess() { return success; }
|
|
|
public String getErrorMessage() { return errorMessage; }
|
|
|
public long getStartTime() { return startTime; }
|
|
|
public long getEndTime() { return endTime; }
|
|
|
}
|
|
|
|
|
|
// 创建边车实例
|
|
|
public Sidecar(String appId) {
|
|
|
this.name = "sidecar-" + appId;
|
|
|
this.appId = appId;
|
|
|
this.executor = Executors.newFixedThreadPool(5);
|
|
|
this.features = new ArrayList<>();
|
|
|
this.running = false;
|
|
|
System.out.println("边车初始化: " + name + " 关联应用: " + appId);
|
|
|
}
|
|
|
|
|
|
// 添加边车功能
|
|
|
public void addFeature(SidecarFeature feature) {
|
|
|
if (feature != null) {
|
|
|
features.add(feature);
|
|
|
System.out.println("添加边车功能: " + feature.getName());
|
|
|
// 如果边车已运行,立即启动新功能
|
|
|
if (running) {
|
|
|
feature.start();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 启动边车
|
|
|
public synchronized void start() {
|
|
|
if (!running) {
|
|
|
running = true;
|
|
|
System.out.println("边车启动: " + name);
|
|
|
|
|
|
// 启动所有功能
|
|
|
for (SidecarFeature feature : features) {
|
|
|
try {
|
|
|
feature.start();
|
|
|
} catch (Exception e) {
|
|
|
System.err.println("启动边车功能失败: " + feature.getName() + ", 错误: " + e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 停止边车
|
|
|
public synchronized void stop() {
|
|
|
if (running) {
|
|
|
running = false;
|
|
|
System.out.println("边车停止: " + name);
|
|
|
|
|
|
// 停止所有功能
|
|
|
for (SidecarFeature feature : features) {
|
|
|
try {
|
|
|
feature.stop();
|
|
|
} catch (Exception e) {
|
|
|
System.err.println("停止边车功能失败: " + feature.getName() + ", 错误: " + e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 关闭线程池
|
|
|
executor.shutdown();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 处理请求(异步)
|
|
|
public void handleRequestAsync(String requestId, String path) {
|
|
|
if (!running) {
|
|
|
System.err.println("边车未运行,无法处理请求: " + requestId);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
RequestContext context = new RequestContext(requestId, path);
|
|
|
requestCount.incrementAndGet();
|
|
|
|
|
|
executor.submit(() -> {
|
|
|
try {
|
|
|
for (SidecarFeature feature : features) {
|
|
|
feature.handleRequest(context);
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
errorCount.incrementAndGet();
|
|
|
context.markError(e.getMessage());
|
|
|
System.err.println("处理请求出错: " + requestId + ", 错误: " + e.getMessage());
|
|
|
} finally {
|
|
|
if (context.isSuccess() && context.getEndTime() == 0) {
|
|
|
context.complete();
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 处理请求(同步)
|
|
|
public void handleRequestSync(String requestId, String path) {
|
|
|
if (!running) {
|
|
|
System.err.println("边车未运行,无法处理请求: " + requestId);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
RequestContext context = new RequestContext(requestId, path);
|
|
|
requestCount.incrementAndGet();
|
|
|
|
|
|
try {
|
|
|
for (SidecarFeature feature : features) {
|
|
|
feature.handleRequest(context);
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
errorCount.incrementAndGet();
|
|
|
context.markError(e.getMessage());
|
|
|
System.err.println("处理请求出错: " + requestId + ", 错误: " + e.getMessage());
|
|
|
} finally {
|
|
|
if (context.isSuccess() && context.getEndTime() == 0) {
|
|
|
context.complete();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 获取统计信息
|
|
|
public String getStats() {
|
|
|
return String.format("边车统计 - 应用: %s, 请求数: %d, 错误数: %d, 运行状态: %s",
|
|
|
appId, requestCount.get(), errorCount.get(), running ? "运行中" : "已停止");
|
|
|
}
|
|
|
|
|
|
// 获取运行状态
|
|
|
public boolean isRunning() {
|
|
|
return running;
|
|
|
}
|
|
|
|
|
|
// 获取边车名称
|
|
|
public String getName() {
|
|
|
return name;
|
|
|
}
|
|
|
|
|
|
// 内置日志功能实现
|
|
|
public static class LoggingFeature implements SidecarFeature {
|
|
|
@Override
|
|
|
public String getName() {
|
|
|
return "日志功能";}
|
|
|
|
|
|
@Override
|
|
|
public void start() {
|
|
|
System.out.println("日志功能已启动");
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void stop() {
|
|
|
System.out.println("日志功能已停止");
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void handleRequest(RequestContext context) {
|
|
|
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
|
|
|
String status = context.isSuccess() ? "SUCCESS" : "ERROR";
|
|
|
System.out.println(String.format("[%s] [%s] 请求: %s, 路径: %s, 状态: %s, 耗时: %dms",
|
|
|
timestamp, Thread.currentThread().getName(),
|
|
|
context.getRequestId(), context.getPath(), status, context.getDuration()));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 内置监控功能实现
|
|
|
public static class MonitoringFeature implements SidecarFeature {
|
|
|
private final AtomicInteger requestCounter = new AtomicInteger(0);
|
|
|
|
|
|
@Override
|
|
|
public String getName() {
|
|
|
return "监控功能";}
|
|
|
|
|
|
@Override
|
|
|
public void start() {
|
|
|
System.out.println("监控功能已启动");
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void stop() {
|
|
|
System.out.println("监控功能已停止");
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void handleRequest(RequestContext context) {
|
|
|
int count = requestCounter.incrementAndGet();
|
|
|
if (count % 5 == 0) {
|
|
|
System.out.println("监控统计: 已处理 " + count + " 个请求");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
} |