feat:多机证书导入功能
This commit is contained in:
@@ -8,6 +8,8 @@ import com.sunyard.inf.customize.SydQNUCApi;
|
||||
import com.sunyard.inf.customize.SydUnionPayApi;
|
||||
import racal.sunyard.main.SydApiBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Cheney on 2017/11/11.
|
||||
* 程序调用接口
|
||||
@@ -117,4 +119,6 @@ public interface SydApi extends
|
||||
public Object getBindObject();
|
||||
|
||||
public void setBindObject(Object bindObject);
|
||||
|
||||
void importCertToServers(List<String> addressList, int timeout, String cert);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.sunyard.entity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ServerConfig {
|
||||
|
||||
/**
|
||||
* 主机节点信息
|
||||
*/
|
||||
private List<ServerAddress> masterNodeList;
|
||||
|
||||
/**
|
||||
* 备机节点信息
|
||||
*/
|
||||
private List<ServerAddress> slaveNodeList;
|
||||
|
||||
|
||||
/**
|
||||
* 连接超时时间
|
||||
*/
|
||||
private Integer timeout;
|
||||
|
||||
public ServerConfig(List<ServerAddress> masterNodeList, List<ServerAddress> slaveNodeList, Integer timeout) {
|
||||
this.masterNodeList = masterNodeList;
|
||||
this.slaveNodeList = slaveNodeList;
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public List<ServerAddress> getMasterNodeList() {
|
||||
return masterNodeList;
|
||||
}
|
||||
|
||||
public void setMasterNodeList(List<ServerAddress> masterNodeList) {
|
||||
this.masterNodeList = masterNodeList;
|
||||
}
|
||||
|
||||
public Integer getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public void setTimeout(Integer timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public List<ServerAddress> getSlaveNodeList() {
|
||||
return slaveNodeList;
|
||||
}
|
||||
|
||||
public void setSlaveNodeList(List<ServerAddress> slaveNodeList) {
|
||||
this.slaveNodeList = slaveNodeList;
|
||||
}
|
||||
|
||||
|
||||
public static class ServerAddress {
|
||||
|
||||
|
||||
private String ip;
|
||||
|
||||
private Integer port;
|
||||
|
||||
public ServerAddress(String ip, Integer port) {
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.sunyard.snmp;
|
||||
|
||||
import org.snmp4j.*;
|
||||
import org.snmp4j.mp.*;
|
||||
import org.snmp4j.security.*;
|
||||
import org.snmp4j.smi.*;
|
||||
import org.snmp4j.transport.DefaultUdpTransportMapping;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Vector;
|
||||
|
||||
public class SnmpTrapSender {
|
||||
private static volatile SnmpTrapSender instance;
|
||||
private Snmp snmp;
|
||||
private Properties config;
|
||||
|
||||
// 配置参数
|
||||
private String ip;
|
||||
private int port;
|
||||
private String enterpriseOid;
|
||||
private String community;
|
||||
private int version;
|
||||
|
||||
|
||||
private SnmpTrapSender() throws IOException {
|
||||
// loadConfig();
|
||||
ip = "172.16.18.113";
|
||||
port = 162;
|
||||
enterpriseOid = "1.3.6.1.4.1.2021.251.1";
|
||||
community = "public";
|
||||
version = 1;
|
||||
initializeSNMP();
|
||||
}
|
||||
|
||||
public static SnmpTrapSender getInstance() throws IOException {
|
||||
if (instance == null) {
|
||||
synchronized (SnmpTrapSender.class) {
|
||||
if (instance == null) {
|
||||
instance = new SnmpTrapSender();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void loadConfig() {
|
||||
try (InputStream input = getClass().getClassLoader().getResourceAsStream("test.properties")) {
|
||||
config = new Properties();
|
||||
config.load(input);
|
||||
|
||||
ip = config.getProperty("snmp.target.ip");
|
||||
port = Integer.parseInt(config.getProperty("snmp.target.port"));
|
||||
enterpriseOid = config.getProperty("enterprise.oid");
|
||||
community = config.getProperty("snmp.community");
|
||||
version = Integer.parseInt(config.getProperty("snmp.version"));
|
||||
|
||||
} catch (IOException | NumberFormatException e) {
|
||||
throw new RuntimeException("加载配置文件失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadConfig(Map<String, String> map) {
|
||||
ip = map.getOrDefault("snmp.target.ip", null);
|
||||
// port = Integer.parseInt(map.getOrDefault("snmp.target.port", "0"));
|
||||
enterpriseOid = map.getOrDefault("enterprise.oid", null);
|
||||
community = map.getOrDefault("snmp.community", null);
|
||||
// version = Integer.parseInt(map.getOrDefault("snmp.version", "1"));
|
||||
}
|
||||
|
||||
private void initializeSNMP() throws IOException {
|
||||
TransportMapping<?> transport = new DefaultUdpTransportMapping();
|
||||
snmp = new Snmp(transport);
|
||||
snmp.listen();
|
||||
}
|
||||
|
||||
public void sendTrap(String message, int severity) throws IOException {
|
||||
switch (version) {
|
||||
case SnmpConstants.version1:
|
||||
sendV1Trap(message, severity);
|
||||
break;
|
||||
case SnmpConstants.version2c:
|
||||
sendV2Trap(message, severity);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("不支持的SNMP版本");
|
||||
}
|
||||
}
|
||||
|
||||
private void sendV1Trap(String message, int severity) throws IOException {
|
||||
CommunityTarget target = createCommunityTarget(SnmpConstants.version1);
|
||||
PDUv1 pdu = new PDUv1();
|
||||
configureCommonTrap(pdu, message, severity);
|
||||
pdu.setGenericTrap(PDUv1.ENTERPRISE_SPECIFIC);
|
||||
snmp.send(pdu, target);
|
||||
}
|
||||
|
||||
private void sendV2Trap(String message, int severity) throws IOException {
|
||||
CommunityTarget target = createCommunityTarget(SnmpConstants.version2c);
|
||||
PDU pdu = new PDU();
|
||||
configureCommonTrap(pdu, message, severity);
|
||||
pdu.setType(PDU.TRAP);
|
||||
snmp.send(pdu, target);
|
||||
}
|
||||
|
||||
|
||||
private void configureCommonTrap(PDU pdu, String message, int severity) {
|
||||
pdu.add(new VariableBinding(SnmpConstants.sysUpTime,
|
||||
new TimeTicks(System.currentTimeMillis()/1000)));
|
||||
pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID,
|
||||
new OID(enterpriseOid + ".0.1")));
|
||||
pdu.add(new VariableBinding(new OID(enterpriseOid + ".1.1"),
|
||||
new OctetString(message)));
|
||||
pdu.add(new VariableBinding(new OID(enterpriseOid + ".1.2"),
|
||||
new Integer32(severity)));
|
||||
}
|
||||
|
||||
private CommunityTarget createCommunityTarget(int version) {
|
||||
CommunityTarget target = new CommunityTarget();
|
||||
target.setCommunity(new OctetString(community));
|
||||
target.setAddress(GenericAddress.parse("udp:"+ip+"/"+port));
|
||||
target.setVersion(version);
|
||||
target.setTimeout(5000);
|
||||
target.setRetries(3);
|
||||
return target;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (snmp != null) {
|
||||
snmp.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package com.sunyard.task;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class AsyncTaskExecutor {
|
||||
|
||||
private final ExecutorService taskExecutor;
|
||||
private final ScheduledExecutorService retryScheduler;
|
||||
|
||||
public AsyncTaskExecutor(int taskThreads, int retryThreads) {
|
||||
this.taskExecutor = Executors.newFixedThreadPool(taskThreads);
|
||||
this.retryScheduler = Executors.newScheduledThreadPool(retryThreads);
|
||||
}
|
||||
|
||||
// 默认配置构造函数
|
||||
public AsyncTaskExecutor() {
|
||||
this(4, 2);
|
||||
}
|
||||
|
||||
public List<TaskOutcome<String>> execTasks(List<TaskContext<String>> taskContexts) {
|
||||
List<CompletableFuture<String>> futures =
|
||||
taskContexts.stream().map(this::retryWithDelay).collect(Collectors.toList());
|
||||
List<TaskOutcome<String>> taskOutcomes = new ArrayList<>();
|
||||
taskContexts.forEach(task ->
|
||||
retryWithDelay(task).whenCompleteAsync((result, ex) -> {
|
||||
if (ex != null) {
|
||||
// 提取原始异常
|
||||
Throwable rootCause = ex instanceof CompletionException ? ex.getCause() : ex;
|
||||
taskOutcomes.add(new TaskOutcome<>(task, rootCause));
|
||||
} else {
|
||||
taskOutcomes.add(new TaskOutcome<>(task, result));
|
||||
}
|
||||
}));
|
||||
return taskOutcomes;
|
||||
}
|
||||
|
||||
public List<TaskOutcome<String>> execBatchTasks(List<TaskContext<String>> taskContexts) {
|
||||
// 转换每个Future为明确的TaskOutcome类型
|
||||
List<CompletableFuture<TaskOutcome<String>>> futures = taskContexts.stream()
|
||||
.map(task ->
|
||||
retryWithDelay(task)
|
||||
.<TaskOutcome<String>>handle((result, ex) -> {
|
||||
if (ex != null) {
|
||||
// 提取原始异常
|
||||
Throwable cause = ex instanceof CompletionException ? ex.getCause() : ex;
|
||||
return new TaskOutcome<>(task, cause);
|
||||
} else {
|
||||
return new TaskOutcome<>(task, result);
|
||||
}
|
||||
})
|
||||
)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 等待所有任务完成
|
||||
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
|
||||
futures.toArray(new CompletableFuture[0])
|
||||
);
|
||||
|
||||
// 收集处理结果
|
||||
return allFutures.thenApply(v ->
|
||||
futures.stream()
|
||||
.map(CompletableFuture::join)
|
||||
.collect(Collectors.toList())
|
||||
).join();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 带延迟的重试逻辑
|
||||
*/
|
||||
private <T> CompletableFuture<T> retryWithDelay(TaskContext<T> context) {
|
||||
return CompletableFuture.supplyAsync(context.getTask(), taskExecutor)
|
||||
.handleAsync((result, ex) -> {
|
||||
if (ex == null) {
|
||||
return CompletableFuture.completedFuture(result);
|
||||
} else {
|
||||
return handleRetry(context, ex);
|
||||
}
|
||||
}, taskExecutor)
|
||||
.thenCompose(f -> f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 处理重试逻辑
|
||||
*/
|
||||
private <T> CompletableFuture<T> handleRetry(TaskContext<T> context, Throwable ex) {
|
||||
if (context.canRetry()) {
|
||||
context.decreaseRetry();
|
||||
System.out.printf("[重试调度] ID: %s | 延迟: %ss | 剩余重试: %d | 错误: %s%n",
|
||||
context.getTaskId(),
|
||||
context.getRetryDelay().getSeconds(),
|
||||
context.getRetriesLeft(),
|
||||
ex.getCause().getMessage());
|
||||
|
||||
// 创建延迟重试的Future
|
||||
CompletableFuture<T> delayedRetry = new CompletableFuture<>();
|
||||
retryScheduler.schedule(() -> {
|
||||
retryWithDelay(context).whenComplete((retryResult, retryEx) -> {
|
||||
if (retryEx != null) {
|
||||
delayedRetry.completeExceptionally(retryEx);
|
||||
} else {
|
||||
delayedRetry.complete(retryResult);
|
||||
}
|
||||
});
|
||||
}, context.getRetryDelay().toMillis(), TimeUnit.MILLISECONDS);
|
||||
|
||||
return delayedRetry;
|
||||
} else {
|
||||
// 重试耗尽,传递原始异常
|
||||
CompletableFuture<T> failed = new CompletableFuture<>();
|
||||
failed.completeExceptionally(ex);
|
||||
return failed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭线程池
|
||||
*/
|
||||
public void shutdown() {
|
||||
taskExecutor.shutdown();
|
||||
retryScheduler.shutdown();
|
||||
try {
|
||||
if (!taskExecutor.awaitTermination(1, TimeUnit.SECONDS)) {
|
||||
taskExecutor.shutdownNow();
|
||||
}
|
||||
if (!retryScheduler.awaitTermination(1, TimeUnit.SECONDS)) {
|
||||
retryScheduler.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.sunyard.task;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class TaskContext<T> {
|
||||
private final String taskId; // 唯一任务ID
|
||||
private final Supplier<T> task; // 原始任务逻辑
|
||||
private int retriesLeft; // 剩余重试次数
|
||||
private final Duration retryDelay; // 重试延迟
|
||||
|
||||
private final String address;
|
||||
|
||||
public TaskContext(Supplier<T> task, int maxRetries, Duration retryDelay, String address) {
|
||||
this.taskId = UUID.randomUUID().toString();
|
||||
this.task = task;
|
||||
this.retriesLeft = maxRetries;
|
||||
this.retryDelay = retryDelay;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public String getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public Supplier<T> getTask() {
|
||||
return task;
|
||||
}
|
||||
|
||||
public int getRetriesLeft() {
|
||||
return retriesLeft;
|
||||
}
|
||||
|
||||
public boolean canRetry() {
|
||||
return retriesLeft > 0;
|
||||
}
|
||||
|
||||
public void decreaseRetry() {
|
||||
retriesLeft--;
|
||||
}
|
||||
|
||||
public Duration getRetryDelay() {
|
||||
return retryDelay;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.sunyard.task;
|
||||
|
||||
public class TaskOutcome<T> {
|
||||
private final TaskContext<T> context;
|
||||
private final T result;
|
||||
private final Throwable error;
|
||||
|
||||
public TaskOutcome(TaskContext<T> context, T result) {
|
||||
this.context = context;
|
||||
this.result = result;
|
||||
this.error = null;
|
||||
}
|
||||
|
||||
public TaskOutcome(TaskContext<T> context, Throwable error) {
|
||||
this.context = context;
|
||||
this.result = null;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return error == null;
|
||||
}
|
||||
|
||||
public TaskContext<T> getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public T getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public Throwable getError() {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user