Compare commits
2
Commits
6d6a199728
...
862b860020
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
862b860020 | ||
|
|
100fad7d18 |
Generated
+1
@@ -2,5 +2,6 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/dashboard" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -0,0 +1,277 @@
|
|||||||
|
package org.kne.cloud.network;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.DatagramSocket;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
import java.net.SocketOption;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.ClosedChannelException;
|
||||||
|
import java.nio.channels.DatagramChannel;
|
||||||
|
import java.nio.channels.MembershipKey;
|
||||||
|
import java.nio.channels.SelectableChannel;
|
||||||
|
import java.nio.channels.SelectionKey;
|
||||||
|
import java.nio.channels.Selector;
|
||||||
|
import java.nio.channels.spi.SelectorProvider;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自制的 UDP AIO 通道,内部使用线程池模拟异步收包。
|
||||||
|
* 用户只需设置回调,无需自己管理线程。
|
||||||
|
*
|
||||||
|
* 完整委托了 DatagramChannel 的所有公共方法。
|
||||||
|
*/
|
||||||
|
public class AsynchronousDatagramChannel implements AutoCloseable {
|
||||||
|
|
||||||
|
private final DatagramChannel delegate;
|
||||||
|
private final ExecutorService workerPool;
|
||||||
|
private final AtomicBoolean running = new AtomicBoolean(true);
|
||||||
|
private volatile ReceiveHandler handler;
|
||||||
|
private final int bufferSize;
|
||||||
|
private int threadCount;
|
||||||
|
|
||||||
|
// ==================== 回调接口 ====================
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ReceiveHandler {
|
||||||
|
void onReceive(SocketAddress from, ByteBuffer data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 构造方法 ====================
|
||||||
|
|
||||||
|
public AsynchronousDatagramChannel() throws IOException {
|
||||||
|
this(65535, Runtime.getRuntime().availableProcessors());
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsynchronousDatagramChannel(int bufferSize, int threadCount) throws IOException {
|
||||||
|
this.bufferSize = bufferSize;
|
||||||
|
this.delegate = DatagramChannel.open();
|
||||||
|
delegate.configureBlocking(true);
|
||||||
|
this.threadCount=threadCount;
|
||||||
|
this.workerPool = Executors.newFixedThreadPool(threadCount, r -> {
|
||||||
|
Thread t = new Thread(r, "AsyncDatagramReader");
|
||||||
|
t.setDaemon(true);
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startWorkers() {
|
||||||
|
|
||||||
|
for (int i = 0; i < threadCount; i++) {
|
||||||
|
workerPool.submit(this::readerLoop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 核心方法 ====================
|
||||||
|
|
||||||
|
public void setReceiveHandler(ReceiveHandler handler) {
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readerLoop() {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize);
|
||||||
|
while (running.get()) {
|
||||||
|
try {
|
||||||
|
buffer.clear();
|
||||||
|
SocketAddress from = delegate.receive(buffer);
|
||||||
|
if (from == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
buffer.flip();
|
||||||
|
ReceiveHandler localHandler = handler;
|
||||||
|
if (localHandler != null) {
|
||||||
|
localHandler.onReceive(from, buffer);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (running.get()) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int send(ByteBuffer data, SocketAddress target) throws IOException {
|
||||||
|
return delegate.send(data, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== DatagramChannel 委托方法 ====================
|
||||||
|
|
||||||
|
// --- 连接相关 ---
|
||||||
|
|
||||||
|
public DatagramChannel connect(SocketAddress remote) throws IOException {
|
||||||
|
return delegate.connect(remote);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DatagramChannel disconnect() throws IOException {
|
||||||
|
return delegate.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected() {
|
||||||
|
return delegate.isConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 绑定相关 ---
|
||||||
|
|
||||||
|
public DatagramChannel bind(SocketAddress local) throws IOException {
|
||||||
|
return delegate.bind(local);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SocketAddress getLocalAddress() throws IOException {
|
||||||
|
return delegate.getLocalAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SocketAddress getRemoteAddress() throws IOException {
|
||||||
|
return delegate.getRemoteAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 读写相关 ---
|
||||||
|
|
||||||
|
public int read(ByteBuffer dst) throws IOException {
|
||||||
|
return delegate.read(dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long read(ByteBuffer[] dsts) throws IOException {
|
||||||
|
return delegate.read(dsts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
|
||||||
|
return delegate.read(dsts, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int write(ByteBuffer src) throws IOException {
|
||||||
|
return delegate.write(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long write(ByteBuffer[] srcs) throws IOException {
|
||||||
|
return delegate.write(srcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
|
||||||
|
return delegate.write(srcs, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 接收相关 ---
|
||||||
|
|
||||||
|
public SocketAddress receive(ByteBuffer dst) throws IOException {
|
||||||
|
return delegate.receive(dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 多播 (Multicast) ---
|
||||||
|
|
||||||
|
public MembershipKey join(InetAddress group, NetworkInterface interf) throws IOException {
|
||||||
|
return delegate.join(group, interf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MembershipKey join(InetAddress group, NetworkInterface interf, InetAddress source) throws IOException {
|
||||||
|
return delegate.join(group, interf, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 选项相关 ---
|
||||||
|
|
||||||
|
public <T> DatagramChannel setOption(SocketOption<T> name, T value) throws IOException {
|
||||||
|
return delegate.setOption(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T getOption(SocketOption<T> name) throws IOException {
|
||||||
|
return delegate.getOption(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<SocketOption<?>> supportedOptions() {
|
||||||
|
return delegate.supportedOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 阻塞模式 ---
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isBlocking() {
|
||||||
|
return delegate.isBlocking();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 选择器相关 ---
|
||||||
|
|
||||||
|
public SelectableChannel configureBlocking(boolean block) throws IOException {
|
||||||
|
return delegate.configureBlocking(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectorProvider provider() {
|
||||||
|
return delegate.provider();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int validOps() {
|
||||||
|
return delegate.validOps();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectionKey keyFor(Selector sel) {
|
||||||
|
return delegate.keyFor(sel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectionKey register(Selector sel, int ops) throws ClosedChannelException {
|
||||||
|
return delegate.register(sel, ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectionKey register(Selector sel, int ops, Object att) throws ClosedChannelException {
|
||||||
|
return delegate.register(sel, ops, att);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 状态查询 ---
|
||||||
|
|
||||||
|
public boolean isOpen() {
|
||||||
|
return delegate.isOpen() && running.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DatagramSocket socket() {
|
||||||
|
return delegate.socket();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 关闭方法 ====================
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws Exception {
|
||||||
|
running.set(false);
|
||||||
|
workerPool.shutdownNow();
|
||||||
|
delegate.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 静态工厂方法 ====================
|
||||||
|
|
||||||
|
public static AsynchronousDatagramChannel open() throws IOException {
|
||||||
|
return new AsynchronousDatagramChannel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AsynchronousDatagramChannel open(int bufferSize) throws IOException {
|
||||||
|
return new AsynchronousDatagramChannel(bufferSize, Runtime.getRuntime().availableProcessors());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AsynchronousDatagramChannel open(int bufferSize, int threadCount) throws IOException {
|
||||||
|
return new AsynchronousDatagramChannel(bufferSize, threadCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 测试示例 ====================
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
int port = 4567;
|
||||||
|
AsynchronousDatagramChannel channel = AsynchronousDatagramChannel.open();
|
||||||
|
channel.bind(new InetSocketAddress(port));
|
||||||
|
|
||||||
|
channel.setReceiveHandler((from, data) -> {
|
||||||
|
byte[] bytes = new byte[data.remaining()];
|
||||||
|
data.get(bytes);
|
||||||
|
String msg = new String(bytes);
|
||||||
|
System.out.println("Received from " + from + ": " + msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
System.out.println("Echo server running on port " + port);
|
||||||
|
System.out.println("Press Enter to stop...");
|
||||||
|
System.in.read();
|
||||||
|
|
||||||
|
channel.close();
|
||||||
|
System.out.println("Server stopped.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,14 +17,8 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.ThreadFactory;
|
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
@@ -67,7 +61,7 @@ public class KLALBController {
|
|||||||
public HighAccuracyClock getClock() {
|
public HighAccuracyClock getClock() {
|
||||||
return clock;
|
return clock;
|
||||||
}
|
}
|
||||||
private final long TIME_WINDOW=2000000000L;
|
private final long TIME_WINDOW=50000000000L;
|
||||||
private SpeedAndTrafficMonitorDataImpl linkMonitor = new SpeedAndTrafficMonitorDataImpl(
|
private SpeedAndTrafficMonitorDataImpl linkMonitor = new SpeedAndTrafficMonitorDataImpl(
|
||||||
new HashMapTimestampMonitor<UUID>(HighAccuracyClock.SYSTEM_CLOCK, "up", 100,TIME_WINDOW ),
|
new HashMapTimestampMonitor<UUID>(HighAccuracyClock.SYSTEM_CLOCK, "up", 100,TIME_WINDOW ),
|
||||||
new HashMapTimestampMonitor<UUID>(HighAccuracyClock.SYSTEM_CLOCK, "down", 100, TIME_WINDOW));
|
new HashMapTimestampMonitor<UUID>(HighAccuracyClock.SYSTEM_CLOCK, "down", 100, TIME_WINDOW));
|
||||||
@@ -104,23 +98,9 @@ public class KLALBController {
|
|||||||
public List<InetAddress> getDnsAddresses() {
|
public List<InetAddress> getDnsAddresses() {
|
||||||
return dnsAddresses;
|
return dnsAddresses;
|
||||||
}
|
}
|
||||||
private ScheduledExecutorService scheduleTimer=Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(),new ThreadFactory() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Thread newThread(Runnable r) {
|
|
||||||
return ThreadTool.makeVDaemonThreadIfSupport("计时器线程", r);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
public ScheduledExecutorService getScheduleTimer() {
|
|
||||||
return scheduleTimer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Timer twk = new Timer("网卡检测扫描计时器", true);
|
|
||||||
|
|
||||||
|
|
||||||
|
private Runnable tsk1 = new Runnable() {
|
||||||
private TimerTask tsk1 = new TimerTask() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -306,7 +286,7 @@ public class KLALBController {
|
|||||||
return srv6Router.getLocator().getAddress().toInet6Address().equals(inetAddress);
|
return srv6Router.getLocator().getAddress().toInet6Address().equals(inetAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TimerTask tsk2 = new TimerTask() {
|
private Runnable tsk2 = new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -686,7 +666,7 @@ public class KLALBController {
|
|||||||
context.syncToSystem();
|
context.syncToSystem();
|
||||||
// System.out.println(context);
|
// System.out.println(context);
|
||||||
try {
|
try {
|
||||||
NTPv4Protocol nvc = new NTPv4Protocol(context,
|
/*NTPv4Protocol nvc = new NTPv4Protocol(context,
|
||||||
new MultiProtocolSocketAddress(iproxyname + "datagram","0.0.0.0",123));
|
new MultiProtocolSocketAddress(iproxyname + "datagram","0.0.0.0",123));
|
||||||
srv6Router.addSRv6RouterListener(new SRv6RouterListener() {
|
srv6Router.addSRv6RouterListener(new SRv6RouterListener() {
|
||||||
|
|
||||||
@@ -718,7 +698,7 @@ public class KLALBController {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});*/
|
||||||
nvc2 = new NTPv4Protocol(context, new MultiProtocolSocketAddress("udp","0.0.0.0",0));
|
nvc2 = new NTPv4Protocol(context, new MultiProtocolSocketAddress("udp","0.0.0.0",0));
|
||||||
|
|
||||||
System.out.println(" Loaded: NTP Module");
|
System.out.println(" Loaded: NTP Module");
|
||||||
@@ -734,8 +714,8 @@ public class KLALBController {
|
|||||||
private void loadController() {
|
private void loadController() {
|
||||||
this.apiServer = new KLALBRoutingProtocolAPIServer(routingProtocol, this);
|
this.apiServer = new KLALBRoutingProtocolAPIServer(routingProtocol, this);
|
||||||
this.apiClient = new KLALBRoutingProtocolAPIClient(routingProtocol);
|
this.apiClient = new KLALBRoutingProtocolAPIClient(routingProtocol);
|
||||||
twk.schedule(tsk1, 5000, 5000);
|
KLALBScheduler.getScheduler().scheduleAtFixedRate(tsk1, 5000, 5000,TimeUnit.MILLISECONDS);
|
||||||
twk.schedule(tsk2, 5000, 5000);
|
KLALBScheduler.getScheduler().scheduleAtFixedRate(tsk2, 5000, 5000,TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KLALBController() {
|
public KLALBController() {
|
||||||
@@ -753,17 +733,10 @@ public class KLALBController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void initKLALB(boolean enableVirtualAdapter, IPv6AddressGroup selfg) {
|
protected void initKLALB(boolean enableVirtualAdapter, IPv6AddressGroup selfg) {
|
||||||
ThreadTool.makeVDaemonThread("线路性能采样线程", ()->{
|
KLALBScheduler.getScheduler().scheduleAtFixedRate( ()->{
|
||||||
while(true) {
|
|
||||||
linkMonitor.update();
|
linkMonitor.update();
|
||||||
datatMonitor.update();
|
datatMonitor.update();
|
||||||
try {
|
},1,1,TimeUnit.MILLISECONDS);
|
||||||
Thread.sleep(1);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
loadSRv6ProtocolStack(selfg, enableVirtualAdapter);
|
loadSRv6ProtocolStack(selfg, enableVirtualAdapter);
|
||||||
loadController();
|
loadController();
|
||||||
}
|
}
|
||||||
@@ -856,9 +829,8 @@ public class KLALBController {
|
|||||||
return srv6Router;
|
return srv6Router;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Timer trtr = new Timer("路由表刷新计时器", true);
|
|
||||||
{
|
{
|
||||||
trtr.scheduleAtFixedRate(new TimerTask() {
|
KLALBScheduler.getScheduler().scheduleAtFixedRate(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -869,9 +841,9 @@ public class KLALBController {
|
|||||||
srv6Router.updateRouteTabel();
|
srv6Router.updateRouteTabel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 100, 100);
|
}, 100, 100, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
trtr.scheduleAtFixedRate(new TimerTask() {
|
KLALBScheduler.getScheduler().scheduleAtFixedRate(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -880,7 +852,7 @@ public class KLALBController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}, 10, 10);
|
}, 1, 1,TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPv6Packet createPacketToAddress(IPv6Address addr, int flowlabel, IPv6Packet.IPv6Payload packet) {
|
public IPv6Packet createPacketToAddress(IPv6Address addr, int flowlabel, IPv6Packet.IPv6Payload packet) {
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.locks.Condition;
|
import java.util.concurrent.locks.Condition;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
@@ -570,20 +572,17 @@ public class KLALBRemoteLink extends AbstractControlledIPv6NetworkLink implement
|
|||||||
private ThreadParker tpk=new ThreadParker();
|
private ThreadParker tpk=new ThreadParker();
|
||||||
|
|
||||||
private StateManager stateManager;
|
private StateManager stateManager;
|
||||||
private MonitorUpdater monitorUpdater;
|
private ScheduledFuture<?> monitorUpdater;
|
||||||
private class MonitorUpdater implements Runnable{
|
private class MonitorUpdater implements Runnable{
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (!closed) {
|
if(closed) {
|
||||||
|
monitorUpdater.cancel(false);
|
||||||
|
}else{
|
||||||
status.updateReliability();
|
status.updateReliability();
|
||||||
if(status.getState()!=LinkStatus.DOWN) {
|
if(status.getState()!=LinkStatus.DOWN) {
|
||||||
monitor.update();
|
monitor.update();
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
Thread.sleep(1);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -755,8 +754,7 @@ public class KLALBRemoteLink extends AbstractControlledIPv6NetworkLink implement
|
|||||||
|
|
||||||
protected void startIO() {
|
protected void startIO() {
|
||||||
stateManager=new StateManager();
|
stateManager=new StateManager();
|
||||||
monitorUpdater=new MonitorUpdater();
|
monitorUpdater=KLALBScheduler.getScheduler().scheduleAtFixedRate(new MonitorUpdater(),1,1, TimeUnit.MILLISECONDS);
|
||||||
ThreadTool.makeVDaemonThread("线路性能采样线程", monitorUpdater).start();
|
|
||||||
ThreadTool.makeVDaemonThread("远程线路状态线程", stateManager).start();
|
ThreadTool.makeVDaemonThread("远程线路状态线程", stateManager).start();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package org.kne.cloud.network.klalb;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
|
||||||
|
public class KLALBScheduler {
|
||||||
|
private static final ScheduledExecutorService scheduler;
|
||||||
|
static {
|
||||||
|
scheduler= Executors.newScheduledThreadPool( Runtime.getRuntime().availableProcessors(),
|
||||||
|
(r) -> {
|
||||||
|
Thread t = new Thread(r, "KLALB-Scheduler");
|
||||||
|
t.setDaemon(true); // 守护线程,不阻止 JVM 退出
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public static ScheduledExecutorService getScheduler(){
|
||||||
|
return scheduler;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,8 +7,8 @@ import java.io.IOException;
|
|||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Timer;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.TimerTask;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
@@ -37,8 +37,7 @@ import org.kne.ui.YScrollPane;
|
|||||||
public class KLALBStateGUI3 extends XFrame {
|
public class KLALBStateGUI3 extends XFrame {
|
||||||
|
|
||||||
// ==================== 定时任务相关 ====================
|
// ==================== 定时任务相关 ====================
|
||||||
private TimerTask tsk, tsk2, tsk3, tsk4, tsk5; // 各种定时任务
|
private ScheduledFuture<?> tsk, tsk2, tsk3, tsk4, tsk5; // 各种定时任务
|
||||||
private Timer t, t2, t3; // 定时器
|
|
||||||
|
|
||||||
// ==================== 系统托盘相关 ====================
|
// ==================== 系统托盘相关 ====================
|
||||||
private SystemTray st; // 系统托盘
|
private SystemTray st; // 系统托盘
|
||||||
@@ -705,10 +704,6 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
* 初始化定时器
|
* 初始化定时器
|
||||||
*/
|
*/
|
||||||
private void initTimers(KLALBController kc) {
|
private void initTimers(KLALBController kc) {
|
||||||
t3 = new Timer("监视器刷新线程", true);
|
|
||||||
t2 = new Timer("仪表盘刷新线程", true);
|
|
||||||
t = new Timer("状态刷新线程", true);
|
|
||||||
|
|
||||||
// 创建刷新任务
|
// 创建刷新任务
|
||||||
createRefreshTask(kc, ysp);
|
createRefreshTask(kc, ysp);
|
||||||
}
|
}
|
||||||
@@ -1322,9 +1317,9 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
private void createRefreshTask(KLALBController kc, YScrollPane ysp) {
|
private void createRefreshTask(KLALBController kc, YScrollPane ysp) {
|
||||||
// 线路状态刷新任务
|
// 线路状态刷新任务
|
||||||
if (tsk != null) {
|
if (tsk != null) {
|
||||||
tsk.cancel();
|
tsk.cancel(false);
|
||||||
}
|
}
|
||||||
tsk = new TimerTask() {
|
tsk =KLALBScheduler.getScheduler().scheduleAtFixedRate( new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (isVisible()) {
|
if (isVisible()) {
|
||||||
@@ -1382,28 +1377,26 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
ysp.updateScrool();
|
ysp.updateScrool();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}, 1000, 1000, TimeUnit.MILLISECONDS);
|
||||||
t.scheduleAtFixedRate(tsk, 1000, 1000);
|
|
||||||
|
|
||||||
// 仪表盘数据刷新任务
|
// 仪表盘数据刷新任务
|
||||||
if (tsk2 != null) {
|
if (tsk2 != null) {
|
||||||
tsk2.cancel();
|
tsk2.cancel(false);
|
||||||
}
|
}
|
||||||
tsk2 = new TimerTask() {
|
tsk2 =KLALBScheduler.getScheduler().scheduleAtFixedRate(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (isVisible()) {
|
if (isVisible()) {
|
||||||
updateDashboardData(kc);
|
updateDashboardData(kc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}, 100, 100,TimeUnit.MILLISECONDS);
|
||||||
t2.scheduleAtFixedRate(tsk2, 100, 100);
|
|
||||||
|
|
||||||
// 网络图刷新任务
|
// 网络图刷新任务
|
||||||
if (tsk5 != null) {
|
if (tsk5 != null) {
|
||||||
tsk5.cancel();
|
tsk5.cancel(false);
|
||||||
}
|
}
|
||||||
tsk5 = new TimerTask() {
|
tsk5 = KLALBScheduler.getScheduler().scheduleAtFixedRate(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (isVisible()) {
|
if (isVisible()) {
|
||||||
@@ -1415,8 +1408,7 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
graph.revalidate();
|
graph.revalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}, 1000, 1000,TimeUnit.MILLISECONDS);
|
||||||
t.scheduleAtFixedRate(tsk5, 1000, 1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1764,7 +1756,7 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
public void close() {
|
public void close() {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
if (tsk != null) {
|
if (tsk != null) {
|
||||||
tsk.cancel();
|
tsk.cancel(false);
|
||||||
}
|
}
|
||||||
if (st != null) {
|
if (st != null) {
|
||||||
st.remove(ti);
|
st.remove(ti);
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ import java.awt.Color;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.GridLayout;
|
import java.awt.GridLayout;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Timer;
|
import java.util.Scanner;
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
@@ -26,6 +25,7 @@ import org.kne.cloud.network.ipv6.IPv6Address;
|
|||||||
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
|
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
|
||||||
import org.kne.cloud.network.ipv6.IPv6Packet;
|
import org.kne.cloud.network.ipv6.IPv6Packet;
|
||||||
import org.kne.cloud.network.klalb.KLALBRemoteLink;
|
import org.kne.cloud.network.klalb.KLALBRemoteLink;
|
||||||
|
import org.kne.cloud.network.klalb.KLALBScheduler;
|
||||||
import org.kne.cloud.network.monitor.LinkStatus;
|
import org.kne.cloud.network.monitor.LinkStatus;
|
||||||
import org.kne.cloud.network.monitor.TimestampMonitorValue;
|
import org.kne.cloud.network.monitor.TimestampMonitorValue;
|
||||||
import org.kne.math.Long128;
|
import org.kne.math.Long128;
|
||||||
@@ -38,21 +38,18 @@ import javax.swing.ImageIcon;
|
|||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.event.WindowListener;
|
import java.awt.event.WindowListener;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.swing.JSlider;
|
import javax.swing.JSlider;
|
||||||
|
|
||||||
public class LineMonitorGUI extends XFrame {
|
public class LineMonitorGUI extends XFrame {
|
||||||
private Timer timer;
|
private ScheduledFuture<?> tsk3;
|
||||||
private Timer timer1;
|
|
||||||
private Timer timer2;
|
|
||||||
private Timer timer3;
|
|
||||||
private Timer timer4;
|
|
||||||
private TimerTask tsk3;
|
|
||||||
|
|
||||||
private TimerTask tsk4, tsk5,tsk6,tsk7;
|
private ScheduledFuture<?> tsk4, tsk5,tsk6,tsk7;
|
||||||
private TimerTask d1;
|
private ScheduledFuture<?> d1;
|
||||||
private TimerTask d2;
|
private ScheduledFuture<?> d2;
|
||||||
private TimerTask d3;
|
private ScheduledFuture<?> d3;
|
||||||
private TimerTask d4;
|
private ScheduledFuture<?> d4;
|
||||||
|
|
||||||
private TimeSeries spdup = new TimeSeries(UIEnv.getRsb().getString("uploadspeed"));
|
private TimeSeries spdup = new TimeSeries(UIEnv.getRsb().getString("uploadspeed"));
|
||||||
private TimeSeries spddown = new TimeSeries(UIEnv.getRsb().getString("downloadspeed"));
|
private TimeSeries spddown = new TimeSeries(UIEnv.getRsb().getString("downloadspeed"));
|
||||||
@@ -386,49 +383,45 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
@Override
|
@Override
|
||||||
public void setVisible(boolean b) {
|
public void setVisible(boolean b) {
|
||||||
if (b) {
|
if (b) {
|
||||||
if (timer == null) {
|
if (tsk3 == null) {
|
||||||
timer = new Timer();
|
|
||||||
timer1 = new Timer();
|
tsk3 = KLALBScheduler.getScheduler().scheduleAtFixedRate(new Runnable() {
|
||||||
timer2 = new Timer();
|
|
||||||
timer3 = new Timer();
|
|
||||||
timer4 = new Timer();
|
|
||||||
tsk3 = new TimerTask() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
updateTraffic();
|
updateTraffic();
|
||||||
}
|
}
|
||||||
};
|
}, 25, 25, TimeUnit.MILLISECONDS);
|
||||||
tsk4 = new TimerTask() {
|
tsk4 = KLALBScheduler.getScheduler().scheduleAtFixedRate(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
recordSpeedData();
|
recordSpeedData();
|
||||||
}
|
}
|
||||||
};
|
}, 10, 10, TimeUnit.MILLISECONDS);;
|
||||||
|
|
||||||
tsk5 = new TimerTask() {
|
tsk5 =KLALBScheduler.getScheduler().scheduleAtFixedRate( new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
recordDelayData();
|
recordDelayData();
|
||||||
}
|
}
|
||||||
};
|
}, 10, 10, TimeUnit.MILLISECONDS);
|
||||||
tsk6 = new TimerTask() {
|
tsk6 =KLALBScheduler.getScheduler().scheduleAtFixedRate( new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
recordBufferData();
|
recordBufferData();
|
||||||
}
|
}
|
||||||
};
|
}, 10, 10, TimeUnit.MILLISECONDS);
|
||||||
tsk7 = new TimerTask() {
|
tsk7 = KLALBScheduler.getScheduler().scheduleAtFixedRate( new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
recordCongestionData();
|
recordCongestionData();
|
||||||
}
|
}
|
||||||
};
|
}, 25, 25, TimeUnit.MILLISECONDS);
|
||||||
d1 = new TimerTask() {
|
d1 = KLALBScheduler.getScheduler().scheduleAtFixedRate(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -440,8 +433,8 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
} ,25, 25, TimeUnit.MILLISECONDS);
|
||||||
d2 = new TimerTask() {
|
d2 = KLALBScheduler.getScheduler().scheduleAtFixedRate( new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -454,8 +447,8 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}, 25, 25, TimeUnit.MILLISECONDS);
|
||||||
d3 = new TimerTask() {
|
d3 = KLALBScheduler.getScheduler().scheduleAtFixedRate(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -468,8 +461,8 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}, 25, 25, TimeUnit.MILLISECONDS);
|
||||||
d4 = new TimerTask() {
|
d4 =KLALBScheduler.getScheduler().scheduleAtFixedRate( new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -482,51 +475,32 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}, 25, 25, TimeUnit.MILLISECONDS);
|
||||||
timer.scheduleAtFixedRate(tsk3, 25, 25);
|
|
||||||
timer1.scheduleAtFixedRate(tsk4, 10, 10);
|
|
||||||
timer1.scheduleAtFixedRate(d1, 25, 25);
|
|
||||||
timer2.scheduleAtFixedRate(tsk5, 10, 10);
|
|
||||||
timer2.scheduleAtFixedRate(d2, 25, 25);
|
|
||||||
timer3.scheduleAtFixedRate(tsk6, 10, 10);
|
|
||||||
timer3.scheduleAtFixedRate(d3, 25, 25);
|
|
||||||
timer4.scheduleAtFixedRate(tsk7, 25, 25);
|
|
||||||
timer4.scheduleAtFixedRate(d4, 25, 25);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (tsk3 != null)
|
if (tsk3 != null)
|
||||||
tsk3.cancel();
|
tsk3.cancel(false);
|
||||||
if (tsk4 != null)
|
if (tsk4 != null)
|
||||||
tsk4.cancel();
|
tsk4.cancel(false);
|
||||||
if (tsk5 != null)
|
if (tsk5 != null)
|
||||||
tsk5.cancel();
|
tsk5.cancel(false);
|
||||||
if (tsk6 != null)
|
if (tsk6 != null)
|
||||||
tsk6.cancel();
|
tsk6.cancel(false);
|
||||||
if (tsk7 != null)
|
if (tsk7 != null)
|
||||||
tsk7.cancel();
|
tsk7.cancel(false);
|
||||||
if (d1 != null)
|
if (d1 != null)
|
||||||
d1.cancel();
|
d1.cancel(false);
|
||||||
if (d2 != null)
|
if (d2 != null)
|
||||||
d2.cancel();
|
d2.cancel(false);
|
||||||
if (d3 != null)
|
if (d3 != null)
|
||||||
d3.cancel();
|
d3.cancel(false);
|
||||||
if (d4 != null)
|
if (d4 != null)
|
||||||
d4.cancel();
|
d4.cancel(false);
|
||||||
if (timer != null)
|
tsk3=null;
|
||||||
timer.cancel();
|
|
||||||
if (timer1 != null)
|
|
||||||
timer1.cancel();
|
|
||||||
|
|
||||||
if (timer2 != null)
|
|
||||||
timer2.cancel();
|
|
||||||
|
|
||||||
if (timer3 != null)
|
|
||||||
timer3.cancel();
|
|
||||||
|
|
||||||
if (timer4 != null)
|
|
||||||
timer4.cancel();
|
|
||||||
timer = null;
|
|
||||||
}
|
}
|
||||||
super.setVisible(b);
|
super.setVisible(b);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import java.net.SocketException;
|
|||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.WritableByteChannel;
|
import java.nio.channels.WritableByteChannel;
|
||||||
|
|
||||||
|
import org.kne.cloud.network.klalb.KLALBScheduler;
|
||||||
import org.kne.concurrent.*;
|
import org.kne.concurrent.*;
|
||||||
import org.kne.cloud.network.NetworkPacket;
|
import org.kne.cloud.network.NetworkPacket;
|
||||||
import org.kne.cloud.network.congestion.CongestionAlgorithm;
|
import org.kne.cloud.network.congestion.CongestionAlgorithm;
|
||||||
@@ -254,7 +256,7 @@ public class KLTPOutputStream extends OutputStream implements KLTPPacketConsumer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
tt=controller.getScheduleTimer().scheduleAtFixedRate (r, delaytime, delaytime,TimeUnit.NANOSECONDS);
|
tt= KLALBScheduler.getScheduler().scheduleWithFixedDelay(r, delaytime, delaytime,TimeUnit.NANOSECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
IOException ioex=ioe.get();
|
IOException ioex=ioe.get();
|
||||||
|
|||||||
@@ -67,6 +67,11 @@ public class ArrayListTimestampMonitor<K> implements TimestampMonitor<K> {
|
|||||||
return recordPacket(key,clock.getCurrentTimeNanos(),count,length);
|
return recordPacket(key,clock.getCurrentTimeNanos(),count,length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean recordPacket(K key, int count, int length, long delay, long delayMin) {
|
||||||
|
return recordPacket(key, clock.getCurrentTimeNanos(),count, length, delay,delayMin);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean recordPacket(K key,int count, int length, long delay) {
|
public boolean recordPacket(K key,int count, int length, long delay) {
|
||||||
return recordPacket(key, clock.getCurrentTimeNanos(),count, length, delay);
|
return recordPacket(key, clock.getCurrentTimeNanos(),count, length, delay);
|
||||||
}
|
}
|
||||||
@@ -75,17 +80,22 @@ public class ArrayListTimestampMonitor<K> implements TimestampMonitor<K> {
|
|||||||
return recordPacket(key, timestamp,count, length, Long.MAX_VALUE / 1024);
|
return recordPacket(key, timestamp,count, length, Long.MAX_VALUE / 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean recordPacket(K key, Long128 timestamp, int count, int length, long dsndDelay) {
|
||||||
|
return recordPacket(key, timestamp, count, length, dsndDelay,dsndDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录数据包 - 使用插入排序保持列表有序,添加时间戳验证
|
* 记录数据包 - 使用插入排序保持列表有序,添加时间戳验证
|
||||||
*/
|
*/
|
||||||
public boolean recordPacket(K key, Long128 timestamp,int count, int length, long delay) {
|
public boolean recordPacket(K key, Long128 timestamp,int count, int length, long delay, long dsndDelayMin) {
|
||||||
// 验证时间戳的合理性
|
// 验证时间戳的合理性
|
||||||
validateTimestamp(timestamp);
|
validateTimestamp(timestamp);
|
||||||
|
|
||||||
// 快速路径:尝试sequence=0
|
// 快速路径:尝试sequence=0
|
||||||
TimestampMonitorKey<K> monitorKey = new TimestampMonitorKey<>(key, 0);
|
TimestampMonitorKey<K> monitorKey = new TimestampMonitorKey<>(key, 0);
|
||||||
TimestampMonitorValue monitorValue = new TimestampMonitorValue(monitorKey, timestamp,count, length, delay);
|
TimestampMonitorValue monitorValue = new TimestampMonitorValue(monitorKey, timestamp,count, length, delay,dsndDelayMin);
|
||||||
autoCleanup(cleanupThreshold);
|
autoCleanup(cleanupThreshold);
|
||||||
|
|
||||||
rwLock.writeLock().lock();
|
rwLock.writeLock().lock();
|
||||||
@@ -461,6 +471,48 @@ public class ArrayListTimestampMonitor<K> implements TimestampMonitor<K> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从已排序的列表中计算数据量 - 优化版本,只需要startTime
|
||||||
|
*/
|
||||||
|
private long calculateMinDelayFromSortedList(List<TimestampMonitorValue> sortedList, Long128 startTime) {
|
||||||
|
if (sortedList.isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用二分查找找到第一个 >= startTime 的元素位置
|
||||||
|
int startIndex = findFirstValidIndexFromSorted(sortedList, startTime);
|
||||||
|
|
||||||
|
if (startIndex >= sortedList.size()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算从startIndex到末尾的所有数据量(因为数据包不会来自未来)
|
||||||
|
long sum = Long.MAX_VALUE/1024;
|
||||||
|
for (int i = startIndex; i < sortedList.size(); i++) {
|
||||||
|
sum =Math.min(sortedList.get(i).getDelayMin(),sum) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long calculateMinDelay(long timeWindowNs){
|
||||||
|
return calculateMinDelay(clock.getCurrentTimeNanos(),timeWindowNs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long calculateMinDelay(Long128 currentTime, long timeWindowNs){
|
||||||
|
Long128 startTime = currentTime.subtract(Long128.valueOf(timeWindowNs));
|
||||||
|
rwLock.readLock().lock();
|
||||||
|
try {
|
||||||
|
return calculateMinDelayFromSortedList(entries, startTime);
|
||||||
|
} finally {
|
||||||
|
rwLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private volatile TimestampMonitorValue recent=null;
|
private volatile TimestampMonitorValue recent=null;
|
||||||
@Override
|
@Override
|
||||||
public TimestampMonitorValue getRecentDelayEntry() {
|
public TimestampMonitorValue getRecentDelayEntry() {
|
||||||
|
|||||||
@@ -76,15 +76,22 @@ private String name;
|
|||||||
return recordPacket(key,clock.getCurrentTimeNanos(),count,length,delay);
|
return recordPacket(key,clock.getCurrentTimeNanos(),count,length,delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean recordPacket(K key, int count, int length, long delay, long delayMin) {
|
||||||
|
return recordPacket(key,clock.getCurrentTimeNanos(),count,length,delay,delayMin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean recordPacket(K key, Long128 timestamp,int count, int length, long delay) {
|
||||||
|
return recordPacket(key,timestamp,count,length,delay,delay);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 超高性能记录数据包 - 针对路由器优化
|
* 超高性能记录数据包 - 针对路由器优化
|
||||||
*/
|
*/
|
||||||
public boolean recordPacket(K key, Long128 timestamp,int count, int length, long delay) {
|
public boolean recordPacket(K key, Long128 timestamp,int count, int length, long delay,long delayMin) {
|
||||||
autoCleanup(cleanupThreshold);
|
autoCleanup(cleanupThreshold);
|
||||||
// 快速路径:尝试sequence=0
|
// 快速路径:尝试sequence=0
|
||||||
TimestampMonitorKey<K> monitorKey = new TimestampMonitorKey<>(key, 0);
|
TimestampMonitorKey<K> monitorKey = new TimestampMonitorKey<>(key, 0);
|
||||||
TimestampMonitorValue monitorValue = new TimestampMonitorValue(monitorKey,timestamp, count,length,delay);
|
TimestampMonitorValue monitorValue = new TimestampMonitorValue(monitorKey,timestamp, count,length,delay,delayMin);
|
||||||
|
|
||||||
if (entries.putIfAbsent(monitorKey, monitorValue) == null) {
|
if (entries.putIfAbsent(monitorKey, monitorValue) == null) {
|
||||||
totalDataSize.add(length);
|
totalDataSize.add(length);
|
||||||
@@ -304,6 +311,17 @@ private String name;
|
|||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long calculateMinDelay(long timeWindowNs) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long calculateMinDelay(Long128 currentTime, long timeWindowNs) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TimestampMonitorValue getRecentDelayEntry() {
|
public TimestampMonitorValue getRecentDelayEntry() {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|||||||
@@ -19,26 +19,28 @@ public class SpeedAndTrafficAndDelayMonitorDataImpl extends SpeedAndTrafficMonit
|
|||||||
upSampler.update();
|
upSampler.update();
|
||||||
downSampler.update();
|
downSampler.update();
|
||||||
if(upSampler.getSnapshotPacketCount()>0&&upSampler.getSnapshotTotalDelay()>0) {
|
if(upSampler.getSnapshotPacketCount()>0&&upSampler.getSnapshotTotalDelay()>0) {
|
||||||
getUploadBandwidth(). recordPacket(KLALBUtils.createGlobalUUID(),0, 0, upSampler.getAvgDelayNanos());
|
getUploadBandwidth(). recordPacket(KLALBUtils.createGlobalUUID(),0, 0, upSampler.getAvgDelayNanos(),upSampler.getMinDelayNanos());
|
||||||
long odelay=upSampler.getMinDelayNanos();
|
/*long odelay=upSampler.getMinDelayNanos();
|
||||||
if(outDelayMin==Long.MAX_VALUE||odelay<=outDelayMin) {
|
if(outDelayMin==Long.MAX_VALUE||odelay<=outDelayMin) {
|
||||||
outDelayMin=odelay;
|
outDelayMin=odelay;
|
||||||
}else{
|
}else{
|
||||||
outDelayMin=Math.min(odelay, outDelayMin+10000);
|
outDelayMin=Math.min(odelay, outDelayMin+10000);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
if(downSampler.getSnapshotPacketCount()>0&&downSampler.getSnapshotTotalDelay()>0) {
|
if(downSampler.getSnapshotPacketCount()>0&&downSampler.getSnapshotTotalDelay()>0) {
|
||||||
getDownloadBandwidth(). recordPacket(KLALBUtils.createGlobalUUID(),0, 0, downSampler.getAvgDelayNanos());
|
getDownloadBandwidth(). recordPacket(KLALBUtils.createGlobalUUID(),0, 0, downSampler.getAvgDelayNanos(),downSampler.getMinDelayNanos());
|
||||||
long idelay=downSampler.getMinDelayNanos();
|
long idelay=downSampler.getMinDelayNanos();
|
||||||
if(inDelayMin==Long.MAX_VALUE||idelay<=inDelayMin) {
|
/*if(inDelayMin==Long.MAX_VALUE||idelay<=inDelayMin) {
|
||||||
inDelayMin=idelay;
|
inDelayMin=idelay;
|
||||||
}else{
|
}else{
|
||||||
inDelayMin=Math.min(idelay, inDelayMin+10000);
|
inDelayMin=Math.min(idelay, inDelayMin+10000);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
long time=System.nanoTime();
|
long time=System.nanoTime();
|
||||||
if(time-stime>timewindowmax) {
|
if(time-stime>timewindowmax) {
|
||||||
|
outDelayMin=getUploadBandwidth().calculateMinDelay(super.getTimeWindowMax());
|
||||||
|
inDelayMin=getDownloadBandwidth().calculateMinDelay(super.getTimeWindowMax());
|
||||||
stime=time;
|
stime=time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ public class SpeedAndTrafficMonitorDataImpl extends MonitorDataImpl implements S
|
|||||||
private TimestampMonitor<UUID>uploadBandwidth;
|
private TimestampMonitor<UUID>uploadBandwidth;
|
||||||
private TimestampMonitor<UUID>downloadBandwidth;
|
private TimestampMonitor<UUID>downloadBandwidth;
|
||||||
private long timewindow=1000000000L;
|
private long timewindow=1000000000L;
|
||||||
private long timewindowmax=1000000000L;
|
private long timewindowmax=50000000000L;
|
||||||
private BandwidthSampler upSampler=new BandwidthSampler();
|
private BandwidthSampler upSampler=new BandwidthSampler();
|
||||||
private BandwidthSampler downSampler=new BandwidthSampler();
|
private BandwidthSampler downSampler=new BandwidthSampler();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private final long TIME_WINDOW=2000000000L;
|
private final long TIME_WINDOW=50000000000L;
|
||||||
public SpeedAndTrafficMonitorDataImpl(HighAccuracyClock clock) {
|
public SpeedAndTrafficMonitorDataImpl(HighAccuracyClock clock) {
|
||||||
super();
|
super();
|
||||||
this.clock=clock;
|
this.clock=clock;
|
||||||
@@ -184,25 +184,32 @@ public class SpeedAndTrafficMonitorDataImpl extends MonitorDataImpl implements S
|
|||||||
long op=uploadBandwidth.calculatePacketRate(timewindowmax);
|
long op=uploadBandwidth.calculatePacketRate(timewindowmax);
|
||||||
long ip=uploadBandwidth.calculatePacketRate(timewindowmax);
|
long ip=uploadBandwidth.calculatePacketRate(timewindowmax);
|
||||||
if(os>outSpeeedMax) {
|
if(os>outSpeeedMax) {
|
||||||
outSpeeedMax=(outSpeeedMax+os)/2;
|
outSpeeedMax=os;
|
||||||
}else {
|
}else {
|
||||||
outSpeeedMax=(outSpeeedMax*999+os)/1000;
|
outSpeeedMax=(outSpeeedMax*999+os)/1000;
|
||||||
}
|
}
|
||||||
if(is>inSpeedMax) {
|
if(is>inSpeedMax) {
|
||||||
inSpeedMax=(inSpeedMax+is)/2;
|
inSpeedMax=is;
|
||||||
}else {
|
}else {
|
||||||
inSpeedMax=(inSpeedMax*999+is)/1000;
|
inSpeedMax=(inSpeedMax*999+is)/1000;
|
||||||
}
|
}
|
||||||
if(op>outPPSMax) {
|
if(op>outPPSMax) {
|
||||||
outPPSMax=(outPPSMax+op)/2;
|
outPPSMax=op;
|
||||||
}else {
|
}else {
|
||||||
outPPSMax=(outPPSMax*999+op)/1000;
|
outPPSMax=(outPPSMax*999+op)/1000;
|
||||||
}
|
}
|
||||||
if(ip>inPPSMax) {
|
if(ip>inPPSMax) {
|
||||||
inPPSMax=(inPPSMax+ip)/2;
|
inPPSMax=ip;
|
||||||
}else {
|
}else {
|
||||||
inPPSMax=(inPPSMax*999+ip)/1000;
|
inPPSMax=(inPPSMax*999+ip)/1000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected long getTimeWindow() {
|
||||||
|
return timewindow;
|
||||||
|
}
|
||||||
|
protected long getTimeWindowMax() {
|
||||||
|
return timewindowmax;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.kne.cloud.network.monitor;
|
package org.kne.cloud.network.monitor;
|
||||||
|
|
||||||
import org.kne.cloud.clock.HighAccuracyClock;
|
import org.kne.cloud.clock.HighAccuracyClock;
|
||||||
import org.kne.cloud.network.ipv6.PacketID;
|
|
||||||
import org.kne.math.Long128;
|
import org.kne.math.Long128;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,6 +36,9 @@ public interface TimestampMonitor<K> {
|
|||||||
*/
|
*/
|
||||||
boolean recordPacket(K key,int count, int length);
|
boolean recordPacket(K key,int count, int length);
|
||||||
|
|
||||||
|
boolean recordPacket(K key, int count,int length, long dsndDelay);
|
||||||
|
|
||||||
|
boolean recordPacket(K key, int count, int length, long avgDelayNanos, long minDelayNanos);
|
||||||
/**
|
/**
|
||||||
* 记录数据包(使用指定时间戳)
|
* 记录数据包(使用指定时间戳)
|
||||||
* @param key 数据包标识
|
* @param key 数据包标识
|
||||||
@@ -49,7 +51,9 @@ public interface TimestampMonitor<K> {
|
|||||||
|
|
||||||
boolean recordPacket(K key, Long128 timestamp, int count,int length, long dsndDelay);
|
boolean recordPacket(K key, Long128 timestamp, int count,int length, long dsndDelay);
|
||||||
|
|
||||||
boolean recordPacket(K key, int count,int length, long dsndDelay);
|
|
||||||
|
|
||||||
|
boolean recordPacket(K key, Long128 timestamp, int count,int length, long dsndDelay,long dsndDelayMin);
|
||||||
|
|
||||||
// ==================== 清理维护方法 ====================
|
// ==================== 清理维护方法 ====================
|
||||||
|
|
||||||
@@ -146,6 +150,10 @@ public interface TimestampMonitor<K> {
|
|||||||
long getRecentDelay();
|
long getRecentDelay();
|
||||||
|
|
||||||
|
|
||||||
|
long calculateMinDelay(long timeWindowNs);
|
||||||
|
|
||||||
|
long calculateMinDelay(Long128 currentTime, long timeWindowNs);
|
||||||
|
|
||||||
TimestampMonitorValue getRecentDelayEntry();
|
TimestampMonitorValue getRecentDelayEntry();
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,22 +8,26 @@ public class TimestampMonitorValue implements Comparable<TimestampMonitorValue>
|
|||||||
private final int length;
|
private final int length;
|
||||||
private final TimestampMonitorKey<?> key;
|
private final TimestampMonitorKey<?> key;
|
||||||
private long delay;
|
private long delay;
|
||||||
|
private long delayMin;
|
||||||
public TimestampMonitorValue(TimestampMonitorKey<?> key, Long128 timestamp,int count, int length) {
|
public TimestampMonitorValue(TimestampMonitorKey<?> key, Long128 timestamp,int count, int length) {
|
||||||
this(key,timestamp,count,length,Long.MAX_VALUE/1024);
|
this(key,timestamp,count,length,Long.MAX_VALUE/1024,Long.MAX_VALUE/1024);
|
||||||
}
|
}
|
||||||
public TimestampMonitorValue(TimestampMonitorKey<?> key, Long128 timestamp,int count, int length,long delay) {
|
public TimestampMonitorValue(TimestampMonitorKey<?> key, Long128 timestamp,int count, int length,long delay,long delayMin) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
this.count=count;
|
this.count=count;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
this.delay=delay;
|
this.delay=delay;
|
||||||
|
this.delayMin=delayMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
|
result = prime * result + count;
|
||||||
result = prime * result + (int) (delay ^ (delay >>> 32));
|
result = prime * result + (int) (delay ^ (delay >>> 32));
|
||||||
|
result = prime * result + (int) (delayMin ^ (delayMin >>> 32));
|
||||||
result = prime * result + length;
|
result = prime * result + length;
|
||||||
result = prime * result + ((timestamp == null) ? 0 : timestamp.hashCode());
|
result = prime * result + ((timestamp == null) ? 0 : timestamp.hashCode());
|
||||||
return result;
|
return result;
|
||||||
@@ -38,8 +42,12 @@ public class TimestampMonitorValue implements Comparable<TimestampMonitorValue>
|
|||||||
if (getClass() != obj.getClass())
|
if (getClass() != obj.getClass())
|
||||||
return false;
|
return false;
|
||||||
TimestampMonitorValue other = (TimestampMonitorValue) obj;
|
TimestampMonitorValue other = (TimestampMonitorValue) obj;
|
||||||
|
if (count != other.count)
|
||||||
|
return false;
|
||||||
if (delay != other.delay)
|
if (delay != other.delay)
|
||||||
return false;
|
return false;
|
||||||
|
if (delayMin != other.delayMin)
|
||||||
|
return false;
|
||||||
if (length != other.length)
|
if (length != other.length)
|
||||||
return false;
|
return false;
|
||||||
if (timestamp == null) {
|
if (timestamp == null) {
|
||||||
@@ -52,8 +60,8 @@ public class TimestampMonitorValue implements Comparable<TimestampMonitorValue>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "TimestampMonitorValue [timestamp=" + timestamp + ", length=" + length + ", key=" + key + ", delay="
|
return "TimestampMonitorValue [timestamp=" + timestamp + ", count=" + count + ", length=" + length
|
||||||
+ delay + "]";
|
+ ", delay=" + delay + ", delayMin=" + delayMin + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long128 getTimestamp() { return timestamp; }
|
public Long128 getTimestamp() { return timestamp; }
|
||||||
@@ -73,6 +81,12 @@ public class TimestampMonitorValue implements Comparable<TimestampMonitorValue>
|
|||||||
this.delay = delay;
|
this.delay = delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getDelayMin() {
|
||||||
|
return delayMin;
|
||||||
|
}
|
||||||
|
public void setDelayMin(long delayMin) {
|
||||||
|
this.delayMin = delayMin;
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(TimestampMonitorValue other) {
|
public int compareTo(TimestampMonitorValue other) {
|
||||||
return this.timestamp.compareTo(other.timestamp);
|
return this.timestamp.compareTo(other.timestamp);
|
||||||
|
|||||||
@@ -12,11 +12,10 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.Condition;
|
import java.util.concurrent.locks.Condition;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
@@ -45,11 +44,13 @@ import org.kne.cloud.network.ipv6.PadNHopByHopTLV;
|
|||||||
import org.kne.cloud.network.ipv6.PostcardEntry;
|
import org.kne.cloud.network.ipv6.PostcardEntry;
|
||||||
import org.kne.cloud.network.ipv6.RouteItem;
|
import org.kne.cloud.network.ipv6.RouteItem;
|
||||||
import org.kne.cloud.network.klalb.KLALBRemoteLink;
|
import org.kne.cloud.network.klalb.KLALBRemoteLink;
|
||||||
|
import org.kne.cloud.network.klalb.KLALBScheduler;
|
||||||
import org.kne.cloud.network.klalb.KLALBUtils;
|
import org.kne.cloud.network.klalb.KLALBUtils;
|
||||||
import org.kne.cloud.network.klalb.PerformanceStrategy;
|
import org.kne.cloud.network.klalb.PerformanceStrategy;
|
||||||
import org.kne.cloud.network.klalb.ui.PerformanceStrategyItem;
|
import org.kne.cloud.network.klalb.ui.PerformanceStrategyItem;
|
||||||
import org.kne.concurrent.HighPerformanceExecutor2;
|
import org.kne.concurrent.HighPerformanceExecutor2;
|
||||||
import org.kne.concurrent.TimeoutConcurrentHashMap;
|
import org.kne.concurrent.TimeoutConcurrentHashMap;
|
||||||
|
import org.kne.io.KNEChannels;
|
||||||
import org.pcap4j.packet.IllegalRawDataException;
|
import org.pcap4j.packet.IllegalRawDataException;
|
||||||
|
|
||||||
import com.google.gson.internal.Pair;
|
import com.google.gson.internal.Pair;
|
||||||
@@ -850,7 +851,6 @@ public class SRv6Router {
|
|||||||
private volatile long backplanePPSMax=0;
|
private volatile long backplanePPSMax=0;
|
||||||
private volatile long prevTime=System.nanoTime();
|
private volatile long prevTime=System.nanoTime();
|
||||||
|
|
||||||
private Timer backplaneTimer=new Timer();
|
|
||||||
private void updateBackplaneCounter() {
|
private void updateBackplaneCounter() {
|
||||||
long curr=System.nanoTime();
|
long curr=System.nanoTime();
|
||||||
long totalTime=timeAdder.getAndReset();
|
long totalTime=timeAdder.getAndReset();
|
||||||
@@ -904,13 +904,13 @@ public class SRv6Router {
|
|||||||
linkTabel.add(inLoopBack); // 添加到链路表
|
linkTabel.add(inLoopBack); // 添加到链路表
|
||||||
this.srhInserter=new SRHInsertNetworkLink(this,networkGroup);
|
this.srhInserter=new SRHInsertNetworkLink(this,networkGroup);
|
||||||
linkTabel.add(srhInserter);
|
linkTabel.add(srhInserter);
|
||||||
backplaneTimer.scheduleAtFixedRate(new TimerTask() {
|
KLALBScheduler.getScheduler().scheduleAtFixedRate(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
updateBackplaneCounter();
|
updateBackplaneCounter();
|
||||||
}
|
}
|
||||||
}, 100, 100);
|
}, 100, 100, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user