KLALB大更新

新负载均衡算法
This commit is contained in:
Administrator
2023-07-02 13:20:11 +08:00
parent f743b23e53
commit 585b7c5fe6
59 changed files with 1681 additions and 553 deletions
@@ -17,7 +17,7 @@ public class ACKTPacket extends KLALBPacket {
}
public ACKTPacket() {
super();
super(ACKT);
}
@Override
@@ -22,7 +22,7 @@ public class DATATPacket extends KLALBPacket {
}
public DATATPacket() {
super();
super(DATAT);
}
public int getSport() {
@@ -11,18 +11,24 @@ import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
import java.util.Timer;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.function.Supplier;
import org.kne.cloud.network.mport.MultipurposeSocketAddress;
import org.kne.cloud.network.mport.NetworkService;
import org.kne.cloud.network.mport.ProxyProfileEntry;
import org.kne.cloud.network.mport.ThreadTool;
import javassist.ClassPool;
@@ -33,6 +39,29 @@ import javassist.bytecode.CodeAttribute;
import javassist.bytecode.CodeIterator;
public class KLALBController {
private LineManager lineManager;
private Supplier<String> selflineTableSupplier=()->{return null;};
public Supplier<String> getSelflineTableSupplier() {
return selflineTableSupplier;
}
public void setSelflineTableSupplier(Supplier<String> selflineTableSupplier) {
this.selflineTableSupplier = selflineTableSupplier;
}
public LineManager getLineManager() {
if(lineManager==null)
lineManager=createLineManager();
return lineManager;
}
protected LineManager createLineManager() {
return new LineManager(this);
}
private Inet6Address self;
@@ -70,6 +99,7 @@ public class KLALBController {
}
public void addRemoteSocket(KLALBRemoteSocket krs) {
krs.setController(this);
CountDownLatch cdl = new CountDownLatch(1);
krs.setPacketReceiver((rec) -> {
try {
@@ -139,6 +169,14 @@ public class KLALBController {
VADDRPacket var = (VADDRPacket) rec;
setLine(var.getVaddr(), krs);
cdl.countDown();
}else if(rec instanceof LINESPacket) {
LINESPacket lpt=(LINESPacket) rec;
String s=lpt.getLines();
Scanner scn=new Scanner(s);
while(scn.hasNext()) {
String sn=scn.nextLine();
getLineManager().addHostPort(new MultipurposeSocketAddress(sn));
}
}
} catch (NoRouteToHostException e) {
e.printStackTrace();
@@ -146,8 +184,12 @@ public class KLALBController {
});
krs.setCloseListener((x) -> {
removeLine(krs);
cdl.countDown();
});
krs.sendPacket(new VADDRPacket(self), 65537);
String selflineTable=selflineTableSupplier.get();
if(selflineTable!=null)
krs.sendPacket(new LINESPacket(selflineTable), 65537);
try {
cdl.await();
} catch (InterruptedException e) {
@@ -155,14 +197,14 @@ public class KLALBController {
}
}
public KLALBController() {
this.self = KLALBUtils.uuidToIP(UUID.randomUUID());
}
public KLALBController(Inet6Address self) {
this.self = self;
}
public KLALBController() {
this.self=KLALBUtils.uuidToIP(UUID.randomUUID());
}
private Map<Integer, KLALBVirtualSocketImpl> bindmap = new ConcurrentHashMap<>();
protected Map<Integer, KLALBVirtualSocketImpl> getBindmap() {
@@ -225,7 +267,8 @@ public class KLALBController {
int count0 = Math.min(count, l.size());
List<KLALBRemoteSocket> l2 = (List<KLALBRemoteSocket>) ((ArrayList<KLALBRemoteSocket>) l).clone();
LineDecitionComparator ldc = new LineDecitionComparator(l2, priority);
l2.sort(ldc);
Collections.sort(l2,ldc);
//System.out.println(l2);
for (Iterator<KLALBRemoteSocket> iterator = l2.iterator(); iterator.hasNext();) {
KLALBRemoteSocket krst = (KLALBRemoteSocket) iterator.next();
krst.sendPacket(packet, priority);
@@ -236,7 +279,16 @@ public class KLALBController {
}
}
protected void removeFromSend(Inet6Address addr,KLALBPacket klalbPacket) {
synchronized (routes) {
List<KLALBRemoteSocket> l = routes.get(addr);
if (l != null && !l.isEmpty()) {
l.forEach((x)->{
x.remoeFromSendQueue(klalbPacket);
});
}
}
}
protected boolean checkIsBind(KLALBVirtualSocketImpl klalbVirtualSocketImpl) {
return bindmap.containsValue(klalbVirtualSocketImpl);
}
@@ -245,4 +297,37 @@ private Timer t=new Timer("数据包发送计时器", true);
return t;
}
public void registerToProxyTypeAs(String proxyname) {
MultipurposeSocketAddress.getSocketFactoryRegister().put(proxyname, new KLALBVirtualSocketFactory(this));
MultipurposeSocketAddress.getServerSocketFactoryRegister().put(proxyname, new KLALBVirtualServerSocketFactory(this));
ProxyProfileEntry.getRegister().put(proxyname, new KLALBNetworkService());
}
private class KLALBNetworkService implements NetworkService{
@Override
public void listen(MultipurposeSocketAddress msa) {
// TODO 自动生成的方法存根
}
@Override
public void unlisten(MultipurposeSocketAddress msc) {
// TODO 自动生成的方法存根
}
@Override
public void connect(MultipurposeSocketAddress msa) {
getLineManager().addHostPort(msa);
}
@Override
public void unconnect(MultipurposeSocketAddress msc) {
getLineManager().removeHostPort(msc);
}
}
}
@@ -60,6 +60,10 @@ public class KLALBInputStream extends DataInputStream {
klp=new VADDRPacket();
klp.readFromStream(this);
return klp;
case LINES:
klp=new LINESPacket();
klp.readFromStream(this);
return klp;
}
throw new StreamCorruptedException("unknown package type:"+type);
}
@@ -0,0 +1,72 @@
package org.kne.cloud.network.klalb;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import org.kne.cloud.network.klalb.LineManager.LineEntry;
import org.kne.cloud.network.mport.MultipurposeSocketAddress;
import org.kne.cloud.network.mport.ProxyProfileAnalyser;
import org.kne.cloud.network.mport.ProxyProfileExecutor;
import org.kne.cloud.network.mport.TCPListener;
public class KLALBMain {
public static TCPListener tcpl;
public static ServerPropties sp;
public static KLALBController kc;
public static ProxyProfileExecutor pfa;
public static File f=new File("lines.cfg");
public static void main(String[] args) throws IOException {
System.out.println("KLALB负载均衡V2.0");
sp=new ServerPropties();
System.out.println("虚拟地址:"+sp.getVirtualIP().getHostAddress());
kc=new KLALBController(sp.getVirtualIP());
kc.registerToProxyTypeAs("KLALB");
pfa=new ProxyProfileExecutor();
pfa.load(f);
Scanner scn=new Scanner(System.in);
while(true) {
String s=scn.next();
String[]sc=s.split(" ");
switch(sc[0]) {
case "help":
System.out.print("state:查看线路状态");
System.out.println("reload:重新加载线路配置");
break;
case "reloadlines":
pfa.load(f);
System.out.println("重新加载线路配置成功");
break;
case "state":
LineManager le=kc.getLineManager();
for (Iterator<java.util.Map.Entry<MultipurposeSocketAddress, LineEntry>> iterator = le.entrySet().iterator(); iterator.hasNext();) {
java.util.Map.Entry<MultipurposeSocketAddress, LineEntry> hostPort = iterator.next();
System.out.println(hostPort.getValue() .toString());
}
break;
default:
System.out.println("未知命令,请输入help以查询指令说明");
}
}
}
private static void openPort(int port) throws IOException {
if(tcpl!=null)
tcpl.close();
tcpl=new TCPListener(new MultipurposeSocketAddress("0.0.0.0", port));
tcpl.setCon((soc)->{
KLALBRemoteSocket krs=new KLALBRemoteSocket(soc);
kc.addRemoteSocket(krs);
});
tcpl.open();
}
}
@@ -17,12 +17,9 @@ public abstract class KLALBPacket{
public static final int ACKT=6;
public static final int DATAU=7;
public static final int VADDR=8;
public static final int LINES=9;
private int type;
public KLALBPacket() {
super();
}
public KLALBPacket(int type) {
super();
this.type = type;
@@ -41,6 +38,7 @@ public abstract class KLALBPacket{
}
public long getLength() {
return 4;
return 1;
}
}
@@ -2,7 +2,10 @@ package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.NoRouteToHostException;
import java.net.Socket;
import java.net.SocketException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
@@ -12,12 +15,35 @@ import org.kne.cloud.network.mport.ThreadTool;
public class KLALBRemoteSocket extends MonitoredSocket {
private Inet6Address remoteVaddr;
private KLALBController controller;
public KLALBController getController() {
return controller;
}
protected void setController(KLALBController controller) {
this.controller = controller;
}
public Inet6Address getRemoteVaddr() {
return remoteVaddr;
}
public KLALBRemoteSocket(Socket socket) {
super(socket);
public String toString() {
return super.toString()+ getMonitor().toString();
}
public KLALBRemoteSocket(Socket socket) {
this(socket,new Monitor());
}
public KLALBRemoteSocket(Socket socket,Monitor m) {
super(socket,m);
try {
socket.setSendBufferSize(32768);
socket.setReceiveBufferSize(65535);
//System.out.println(socket.getSendBufferSize()+" "+socket.getReceiveBufferSize());
socket.setTcpNoDelay(true);
socket.setSoTimeout(10000);
} catch (SocketException e1) {
// TODO 自动生成的 catch 块
e1.printStackTrace();
}
ThreadTool.makeVDaemonThreadIfSupport("远程接收线程", () -> {
try {
@@ -25,11 +51,18 @@ public class KLALBRemoteSocket extends MonitoredSocket {
KLALBPacket kpp = getInputStream().readPacket();
//System.out.println("RX:" + kpp);
if(kpp instanceof PINGPacket) {
sendPacket(new PONGPacket(), 65540);
sendPacket(new PONGPacket(((PINGPacket) kpp).getTime()), 65540);
}else if(kpp instanceof PONGPacket) {
latency.set(System.nanoTime()-pingstarttime);
pinging=false;
PONGPacket png=(PONGPacket) kpp;
getMonitor().updateLatency (System.nanoTime()- png.getTime());
try {
socket.setSoTimeout(1100);
} catch (SocketException e1) {
// TODO 自动生成的 catch 块
e1.printStackTrace();
}
}else {
if(kpp instanceof VADDRPacket) {
remoteVaddr=((VADDRPacket) kpp).getVaddr();
}
@@ -40,7 +73,7 @@ public class KLALBRemoteSocket extends MonitoredSocket {
}
}
} catch (IOException e) {
e.printStackTrace();
//e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
@@ -55,18 +88,18 @@ public class KLALBRemoteSocket extends MonitoredSocket {
try {
while (!isClosed()) {
if(System.nanoTime()-pingstarttime>100000000000L) {
pinging=false;
}
if(checkPingTime()&&!pinging) {
getOutputStream().writePacket(new PINGPacket());
pinging =true;
pingstarttime=System.nanoTime();
if(checkPingTime()) {
getOutputStream().writePacket(new PINGPacket(System.nanoTime()));
}else {
PQItem pqi=sendQueue.poll();
if(pqi!=null) {
KLALBPacket kpp=pqi.getPacket();
//if(!(kpp instanceof PONGPacket))
//System.out.println("TX:" + kpp);
if(kpp instanceof PONGPacket) {
PONGPacket pp=(PONGPacket) kpp;
pp.redeltaTime(System.nanoTime()-pqi.getAddtime());
}
getOutputStream().writePacket(kpp);
}else {
Thread.sleep(1);
@@ -74,7 +107,7 @@ public class KLALBRemoteSocket extends MonitoredSocket {
}
}
} catch (IOException e) {
e.printStackTrace();
// e.printStackTrace();
} catch (InterruptedException e) {
} finally {
try {
@@ -87,11 +120,9 @@ public class KLALBRemoteSocket extends MonitoredSocket {
}
private volatile long pingstarttime=System.nanoTime();
private volatile boolean pinging=false;
private volatile long time = System.nanoTime();
private volatile long pingInterval=1000000000L;
private volatile long pingInterval=500000000L;
public long getPingInterval() {
return pingInterval;
@@ -112,11 +143,8 @@ public class KLALBRemoteSocket extends MonitoredSocket {
}
private volatile boolean waitingforPing = false;
public long getLatency() {
return latency.get();
}
private KLALBInputStream kis;
private KLALBOutputStream kos;
@@ -135,7 +163,7 @@ public class KLALBRemoteSocket extends MonitoredSocket {
return kos;
}
private AtomicLong latency = new AtomicLong();
private volatile Consumer<KLALBPacket> rec;
private Consumer<KLALBRemoteSocket> clo;
private PriorityBlockingQueue<PQItem> sendQueue=new PriorityBlockingQueue<PQItem>();
@@ -160,9 +188,22 @@ public class KLALBRemoteSocket extends MonitoredSocket {
}
@Override
public synchronized void close() throws IOException {
super.close();
if(!isClosed()&&clo!=null)
clo.accept(this);
cdl.countDown();
super.close();
sendQueue.forEach((x)->{
try {
controller.sendPacketToAddress(remoteVaddr, x.getPacket(), x.getPriority()+1);
} catch (NoRouteToHostException e) {
}
});
}
@Override
public boolean isClosed() {
return cdl.getCount()<=0;
}
private AtomicLong al=new AtomicLong(0);
@@ -170,6 +211,10 @@ public class KLALBRemoteSocket extends MonitoredSocket {
private KLALBPacket packet;
private long index=al.getAndIncrement();
private int priority=5;
private long addtime=System.nanoTime();
public long getAddtime() {
return addtime;
}
public PQItem(KLALBPacket value, int priority) {
super();
this.packet = value;
@@ -201,4 +246,17 @@ public class KLALBRemoteSocket extends MonitoredSocket {
}
}
}
private CountDownLatch cdl=new CountDownLatch(1);
public void waitforlose() {
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void remoeFromSendQueue(KLALBPacket klalbPacket) {
sendQueue.removeIf((x)->{
return x.getPacket().equals(klalbPacket);
});
}
}
@@ -1,52 +0,0 @@
package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import org.kne.cloud.network.mport.SocketBridge;
import org.kne.cloud.network.mport.TCPListener;
public class KLALBTest1 {
public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {
KLALBRemoteSocket s1=new KLALBRemoteSocket( new Socket("127.0.0.1", 8899));
KLALBRemoteSocket s2=new KLALBRemoteSocket(new Socket("127.0.0.1", 8899));
KLALBRemoteSocket s3=new KLALBRemoteSocket(new Socket("127.0.0.1", 8899));
KLALBController kc=new KLALBController((Inet6Address) Inet6Address.getByName("::2"));
kc.addRemoteSocket(s1);
kc.addRemoteSocket(s2);
kc.addRemoteSocket(s3);
TCPListener tl=new TCPListener(7463);
tl.open();
tl.setCon((x)->{
KLALBVirtualSocket kvs;
try {
kvs = new KLALBVirtualSocket(kc);
kvs.connect(new InetSocketAddress(InetAddress.getByName("::9"), 90));
new SocketBridge(kvs, x).run();
} catch (SocketException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (UnknownHostException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
});
System.out.println("c");
Thread.sleep(20000);
s2.close();
while(true) {
Thread.sleep(1000);
}
}
}
@@ -1,36 +0,0 @@
package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.*;
import org.kne.cloud.network.mport.SocketBridge;
import org.kne.cloud.network.mport.TCPListener;
public class KLALBTest2 {
public static void main(String[] args) throws IOException, InterruptedException {
ServerSocket ssk=new ServerSocket(8899);
KLALBRemoteSocket s1=new KLALBRemoteSocket(ssk.accept());
KLALBRemoteSocket s2=new KLALBRemoteSocket(ssk.accept());
KLALBRemoteSocket s3=new KLALBRemoteSocket(ssk.accept());
KLALBController cont=new KLALBController((Inet6Address) Inet6Address.getByName("::9"));
cont.addRemoteSocket(s1);
cont.addRemoteSocket(s2);
cont.addRemoteSocket(s3);
KLALBVirtualServerSocket ksr=new KLALBVirtualServerSocket(cont);
TCPListener tl=new TCPListener(90);
tl.setServerSocketFactory(new KLALBVirtualServerSocketFactory(cont));
tl.setCon((x)->{
try {
new SocketBridge(x, new Socket("127.0.0.1",5212)).run();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
});
tl.open();
Thread.sleep(20000);
s3.close();
}
}
@@ -29,4 +29,29 @@ public class KLALBUtils {
public static void main(String[] args) {
System.out.println(uuidToIP(new UUID(-1,-1)));
}
public static String bytesUnit(long v) {
if(v>=1024L*1024*1024*1024*1024) {
return format( v/(1024.0*1024.0*1024.0*1024.0*1024.0))+"P";
}else if(v>=1024L*1024*1024*1024) {
return format (v/(1024.0*1024.0*1024.0*1024.0))+"T";
}else if(v>=1024L*1024*1024) {
return format( v/(1024.0*1024.0*1024.0))+"G";
}else if(v>=1024L*1024) {
return format( v/(1024.0*1024.0))+"M";
}else if(v>=1024L) {
return format( v/(1024.0))+"K";
}else {
return v+"B";
}
}
private static String format( double d) {
String fmt=String.format( "%.2f",d);
if(fmt.length()>4) {
fmt=fmt.substring(0, 4);
}
if(fmt.endsWith(".")) {
fmt=fmt.substring(0, fmt.length()-1);
}
return fmt;
}
}
@@ -1,7 +1,7 @@
package org.kne.cloud.network.klalb;
import java.net.SocketException;
import java.net.SocketImpl;
import java.io.IOException;
import java.net.*;
import org.kne.cloud.network.mport.VirtualSocket;
@@ -11,11 +11,52 @@ public class KLALBVirtualSocket extends VirtualSocket {
public KLALBVirtualSocket(KLALBController controler) throws SocketException {
super(controler.createVirtualImpl());
this.controler=controler;
this.controler = controler;
}
protected KLALBController getControler() {
return controler;
}
public KLALBVirtualSocket(KLALBController controler,String host, int port) throws UnknownHostException, IOException {
this(controler,host != null ? new InetSocketAddress(host, port)
: new InetSocketAddress(InetAddress.getByName(null), port), (SocketAddress) null);
}
public KLALBVirtualSocket(KLALBController controler,SocketAddress address, SocketAddress localAddr) throws IOException {
this(controler);
// backward compatibility
if (address == null)
throw new NullPointerException();
try {
if (localAddr != null)
bind(localAddr);
connect(address);
} catch (IOException | IllegalArgumentException | SecurityException e) {
try {
close();
} catch (IOException ce) {
e.addSuppressed(ce);
}
throw e;
}
}
public KLALBVirtualSocket(KLALBController controler,String host, int port, InetAddress localAddr, int localPort) throws IOException {
this(controler,host != null ? new InetSocketAddress(host, port)
: new InetSocketAddress(InetAddress.getByName(null), port),
new InetSocketAddress(localAddr, localPort));
}
public KLALBVirtualSocket(KLALBController controler,InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException {
this(controler,address != null ? new InetSocketAddress(address, port) : null,
new InetSocketAddress(localAddr, localPort));
}
public KLALBVirtualSocket(KLALBController controler,InetAddress address, int port) throws IOException {
this(controler,address != null ? new InetSocketAddress(address, port) : null,
(SocketAddress) null);
}
}
@@ -0,0 +1,39 @@
package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.SocketFactory;
public class KLALBVirtualSocketFactory extends SocketFactory {
private KLALBController controller;
public KLALBVirtualSocketFactory(KLALBController controller) {
super();
this.controller = controller;
}
@Override
public Socket createSocket(String arg0, int arg1) throws IOException, UnknownHostException {
return new KLALBVirtualSocket(controller, arg0, arg1);
}
@Override
public Socket createSocket(InetAddress arg0, int arg1) throws IOException {
return new KLALBVirtualSocket(controller, arg0, arg1);
}
@Override
public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3)
throws IOException, UnknownHostException {
return new KLALBVirtualSocket(controller, arg0, arg1, arg2, arg3);
}
@Override
public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException {
return new KLALBVirtualSocket(controller, arg0, arg1, arg2, arg3);
}
}
@@ -17,14 +17,18 @@ import java.net.SocketException;
import java.net.SocketImpl;
import java.net.SocketOptions;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@@ -51,13 +55,36 @@ public class KLALBVirtualSocketImpl extends SocketImpl {
this.outputchachesize = outputchachesize;
}
private int inputchachesize = 65535 * 50;
private int outputchachesize = 65535 * 50;
private Inet6Address bindaddr;
private int inputchachesize = 5773 * 100;
private int outputchachesize = 5773 * 100;
private Inet6Address bindaddr;{
try {
bindaddr=(Inet6Address) Inet6Address.getByName("::0");
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
private BlockingQueue<InetSocketAddress> backlogQueue;
private BlockingDeque<DATATPacket> sendDeque = new LinkedBlockingDeque<>();
private Queue<DATATPacket> sendDeque = new ConcurrentLinkedQueue<>();
private List<SendTask> sendlist=new Vector<>();
private TimerTask sendCheckTask=new SendCheckTask();
private class SendCheckTask extends TimerTask{
public void run() {
synchronized (sendlist) {
for (int i = 0; i < sendlist.size(); i++) {
try {
sendlist.get(i).check(i);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
}
private boolean succeed, refused;
protected boolean isListening() {
@@ -126,16 +153,18 @@ public class KLALBVirtualSocketImpl extends SocketImpl {
}
}
controller.sendPacketToAddress(from, new ACKTPacket(dtp.getDport(), dtp.getSport(), dtp.getNumber(),
countInputBytes() < inputchachesize), 32768);
countInputBytes() < inputchachesize), 32768,2);
} else if (u instanceof ACKTPacket) {
ACKTPacket ackt = (ACKTPacket) u;
avaliable = ackt.isAvaliable();
AtomicReference<KLALBPacket>kl=new AtomicReference<>();
sendlist.removeIf((tsk)->{
boolean b=tsk.getKp().getNumber()==ackt.getNumber();
if(b)
tsk.cancel();
boolean b=tsk.getPacket().getNumber()==ackt.getNumber();
if(b)
kl.set(tsk.getPacket());
return b;
});
controller.removeFromSend(from,kl.get());
}
} catch (IOException e) {
e.printStackTrace();
@@ -155,7 +184,7 @@ public class KLALBVirtualSocketImpl extends SocketImpl {
private int countOutputBytes() {
AtomicInteger i = new AtomicInteger(0);
sendlist.forEach((c) -> {
i.addAndGet(c.getKp().getData().length);
i.addAndGet(c.getPacket().getData().length);
});
return i.get();
}
@@ -170,17 +199,27 @@ public class KLALBVirtualSocketImpl extends SocketImpl {
public KLALBVirtualSocketImpl(KLALBController kc) {
super();
this.controller = kc;
kc.getTimer().schedule(sendCheckTask, 50, 50);
}
@Override
public void setOption(int optID, Object value) throws SocketException {
// TODO 自动生成的方法存根
if(optID==SocketOptions.SO_RCVBUF) {
inputchachesize=(int) value;
}else if(optID==SocketOptions.SO_SNDBUF) {
outputchachesize=(int)value;
}
}
@Override
public Object getOption(int optID) throws SocketException {
// TODO 自动生成的方法存根
if(optID==SocketOptions.SO_BINDADDR) {
return bindaddr;
}else if(optID==SocketOptions.SO_RCVBUF) {
return inputchachesize;
}else if(optID==SocketOptions.SO_SNDBUF) {
return outputchachesize;
}
return null;
}
@@ -255,6 +294,7 @@ public class KLALBVirtualSocketImpl extends SocketImpl {
@Override
protected void listen(int backlog) throws IOException {
backlogQueue = new ArrayBlockingQueue<>(backlog);
address=bindaddr;
}
private Map<InetSocketAddress, KLALBVirtualSocketImpl> accepts = new ConcurrentHashMap<>();
@@ -268,7 +308,8 @@ public class KLALBVirtualSocketImpl extends SocketImpl {
try {
KLALBVirtualSocketImpl kvsi = (KLALBVirtualSocketImpl) s;
InetSocketAddress isa = backlogQueue.take();
kvsi.inputchachesize=inputchachesize;
kvsi.outputchachesize=outputchachesize;
kvsi.port = isa.getPort();
kvsi.address = isa.getAddress();
kvsi.localport = localport;
@@ -381,21 +422,21 @@ public class KLALBVirtualSocketImpl extends SocketImpl {
private class KVSIOutputStream extends OutputStream {
private ByteArrayOutputStream bos = new ByteArrayOutputStream(65535);
private byte[] cache=new byte[65535];
private int count=0;
@Override
public void write(int b) throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
bos.write(b);
if (bos.size() >= 65535) {
cache[count++]=(byte) b;
if (count >=5773 ) {//1429?
flush();
}
}
@Override
public void flush() throws IOException {
if (bos.size() > 0) {
if (count > 0) {
try {
while (!avaliable) {
Thread.sleep(1);
@@ -411,20 +452,27 @@ public class KLALBVirtualSocketImpl extends SocketImpl {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
SendTask x=new SendTask(controller, (Inet6Address) address, new DATATPacket(localport, port, outputcount++, bos.toByteArray()), 5,5);
x.addToTimer(1000);
byte[]ba;
if(count==cache.length) {
ba=cache;
cache=new byte[cache.length];
}else {
ba=Arrays.copyOf(cache, count);
}
SendTask x=new SendTask(controller, (Inet6Address) address, new DATATPacket(localport, port, outputcount++, ba), 5,10);
x.run();
sendlist.add(x);
/*controller.sendPacketToAddress((Inet6Address) address,
new DATATPacket(localport, port, outputcount++, bos.toByteArray()), 5);*/
}
bos.reset();
count=0;
}
@Override
public void close() throws IOException {
flush();
SendTask x=new SendTask(controller, (Inet6Address) address, new DATATPacket(localport, port, outputcount++, new byte[0]), 5,5);
x.addToTimer(1000);
SendTask x=new SendTask(controller, (Inet6Address) address, new DATATPacket(localport, port, outputcount++, new byte[0]), 5,10);
x.run();
sendlist.add(x);
/*controller.sendPacketToAddress((Inet6Address) address,
new DATATPacket(localport, port, outputcount++, new byte[0]), 5);*/
@@ -480,6 +528,7 @@ public class KLALBVirtualSocketImpl extends SocketImpl {
acceptedSocketCloseListener.accept(this);
else
controller.unbind(this);
sendCheckTask.cancel();
}
private boolean closed;
@@ -0,0 +1,60 @@
package org.kne.cloud.network.klalb;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.net.Inet6Address;
public class LINESPacket extends KLALBPacket {
private String lines;
public String getLines() {
return lines;
}
public LINESPacket(String lines) {
super(LINES);
this.lines=lines;
}
public LINESPacket() {
super(LINES);
}
private int UTFlength(String str) {
int strlen = str.length();
int utflen = 0;
for (int i = 0; i < strlen; i++) {
int c = str.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
utflen++;
} else if (c > 0x07FF) {
utflen += 3;
} else {
utflen += 2;
}
}
return utflen;
}
@Override
public String toString() {
return "LINES\n"+lines;
}
@Override
public long getLength() {
return super.getLength()+2+UTFlength(lines);
}
@Override
protected void writeToStream(DataOutput dto) throws IOException {
super.writeToStream(dto);
dto.writeUTF(lines);
}
@Override
protected void readFromStream(DataInput din) throws IOException {
super.readFromStream(din);
lines=din.readUTF();
}
}
@@ -12,14 +12,15 @@ public class LineDecitionComparator implements Comparator<KLALBRemoteSocket> {
public LineDecitionComparator (List<KLALBRemoteSocket> krs,int priority) {
for (Iterator<KLALBRemoteSocket> iterator = krs.iterator(); iterator.hasNext();) {
KLALBRemoteSocket klalbRemoteSocket = (KLALBRemoteSocket) iterator.next();
long x=klalbRemoteSocket.getLatency()>>1;
long x=klalbRemoteSocket.getMonitor().getLatency()>>1;
x+=klalbRemoteSocket.getMonitor().getJitter()>>1;
AtomicLong al=new AtomicLong(0);
klalbRemoteSocket.getSendQueue().forEach((v)->{
if(v.getPriority()>=priority) {
al.addAndGet(v.getPacket().getLength());
}
});
long speed=klalbRemoteSocket.getOutSpeed();
long speed=klalbRemoteSocket.getMonitor(). getOutSpeedMax();
if(speed==0) {
if(al.get()>0) {
x=Long.MAX_VALUE;
@@ -27,6 +28,7 @@ public class LineDecitionComparator implements Comparator<KLALBRemoteSocket> {
}else {
x+=al.get()*1000000000/speed;
}
//System.out.println(x);
predictedlatencys.put(klalbRemoteSocket, x);
}
}
@@ -0,0 +1,154 @@
package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Hashtable;
import org.kne.cloud.network.klalb.LineManager.LineEntry;
import org.kne.cloud.network.mport.MultipurposeSocketAddress;
import org.kne.cloud.network.mport.ThreadTool;
public class LineManager extends Hashtable<MultipurposeSocketAddress,LineEntry>{
private Object lock=new Object();
private KLALBController controller;
public LineManager(KLALBController controller) {
super();
this.controller = controller;
}
/*public void applyList(HostPortList hpl) {
HostPortList lh=(HostPortList) hpl.clone();
for (Iterator<LineEntry> iterator = hm.iterator(); iterator.hasNext();) {
LineEntry hostPort = (LineEntry) iterator.next();
lh.remove(hostPort.getHp());
}
for (Iterator iterator = lh.iterator(); iterator.hasNext();) {
MultipurposeSocketAddress hostPort = (MultipurposeSocketAddress) iterator.next();
LineEntry le=new LineEntry(hostPort);
hm.add(le);
ThreadTool.makeVDaemonThreadIfSupport("线路监视线程", le).start();
}
for (Iterator<LineEntry> iterator = hm.iterator(); iterator.hasNext();) {
LineEntry hostPort = (LineEntry) iterator.next();
if(!hpl.contains(hostPort.getHp())) {
hostPort.close();
iterator.remove();
}
}
}*/
public void retry() {
synchronized (lock) {
lock.notifyAll();
}
}
public synchronized void addHostPort(MultipurposeSocketAddress v) {
LineEntry le=new LineEntry(v);
if(putIfAbsent(v,le)==null)
le.open();
}
public synchronized void removeHostPort(MultipurposeSocketAddress v) {
for (Iterator<java.util.Map.Entry<MultipurposeSocketAddress, LineEntry>> iterator = entrySet().iterator(); iterator.hasNext();) {
java.util.Map.Entry<MultipurposeSocketAddress, LineEntry> hostPort = iterator.next();
if(hostPort.getValue().equals(v)) {
hostPort.getValue().close();
iterator.remove();
}
}
}
public KLALBController getController() {
return controller;
}
public class LineEntry implements Runnable{
private MultipurposeSocketAddress hp;
private KLALBRemoteSocket krs;
private volatile boolean flag=true;
private volatile boolean online=false;
private Monitor monitor=new Monitor();
public boolean isOnline() {
return online;
}
public MultipurposeSocketAddress getHp() {
return hp;
}
public LineEntry(MultipurposeSocketAddress hp) {
super();
this.hp = hp;
}
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append(online?"●在线 ":"○离线 ");
sb.append(hp.toString());
sb.append('\t');
sb.append(monitor.toString());
return sb.toString();
}
public String toString2() {
StringBuilder sb=new StringBuilder();
sb.append(hp.toString());
sb.append('\n');
sb.append(online?"●在线\t":"○离线\t");
sb.append(monitor.toString2());
return sb.toString();
}
@Override
public void run() {
while(true){
try {
krs=new KLALBRemoteSocket(hp.connectSocket(),monitor);
//System.out.println("open");
controller.addRemoteSocket(krs);
online=true;
krs.waitforlose();
//System.out.println("close");
online=false;
} catch (UnknownHostException e) {
} catch (IOException e) {
//e.printStackTrace();
}
if(!flag) {
break;
}
try {
synchronized (lock) {
lock.wait(10000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void open() {
ThreadTool.makeVDaemonThreadIfSupport("线路监视线程", this).start();
}
public void close() {
flag=false;
if(krs!=null)
try {
krs.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
@@ -0,0 +1,106 @@
package org.kne.cloud.network.klalb;
import java.util.concurrent.atomic.AtomicLong;
import static org.kne.cloud.network.klalb.KLALBUtils.*;
public class Monitor {
private AtomicLong inTraffic=new AtomicLong();
private AtomicLong outTraffic=new AtomicLong();
private AtomicLong inTrafficOld=new AtomicLong();
private AtomicLong outTrafficOld=new AtomicLong();
private volatile long inSpeed;
private volatile long outSpeed;
private volatile long inSpeedMax;
private volatile long outSpeedMax;
private volatile long latency ;
private volatile long jitter ;
public long getInSpeedMax() {
return inSpeedMax;
}
public void updateLatency(long newlatency) {
long vj=Math.abs( latency-newlatency);;
if(jitter<vj) {
jitter=vj;
}else {
jitter=(9*jitter+vj)/10;
}
if(newlatency<latency) {
latency=newlatency;
}else {
this.latency=(latency*9+ newlatency)/10;
}
}
public long getOutSpeedMax() {
return outSpeedMax;
}
public long getInTraffic() {
return inTraffic.get();
}
public long getOutTraffic() {
return outTraffic.get();
}
public AtomicLong getInTrafficAL() {
return inTraffic;
}
public long getJitter() {
return jitter;
}
public AtomicLong getOutTrafficAL() {
return outTraffic;
}
public long getInSpeed() {
return inSpeed;
}
public long getOutSpeed() {
return outSpeed;
}
public void updateSpeed() {
long i=inTraffic.get()-inTrafficOld.get();
long o=outTraffic.get()-outTrafficOld.get();
inTrafficOld.set(inTraffic.get());
outTrafficOld.set(outTraffic.get());
inSpeed= i;
outSpeed= o;
if(inSpeed>inSpeedMax) {
inSpeedMax=inSpeed;
}else {
inSpeedMax=(inSpeedMax*999+inSpeed)/1000;
}
if(outSpeed>outSpeedMax) {
outSpeedMax=outSpeed;
}else {
outSpeedMax=(outSpeedMax*999+outSpeed)/1000;
}
}
public long getLatency() {
return latency;
}
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append(bytesUnit(outTraffic.get())).append("\u2191\t").append(bytesUnit(inTraffic.get())).append("\u2193\t").append(bytesUnit(outSpeed)).append("/s\u2191\t").append(bytesUnit(inSpeed)).append("/s\u2193\t").append(latency/1000000).append("ms");
return sb.toString();
}
public String toString2() {
StringBuilder sb=new StringBuilder();
sb.append(bytesUnit(outTraffic.get())).append("\t").append(bytesUnit(inTraffic.get())).append("\t").append(bytesUnit(outSpeed)).append("/s\t").append(bytesUnit(inSpeed)).append("/s\t").append(latency/1000000).append("ms").append("\t").append(jitter/1000000).append("ms");
return sb.toString();
}
}
@@ -1,15 +1,15 @@
package org.kne.cloud.network.klalb;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.atomic.AtomicLong;
public class MonitoredInputStream extends InputStream {
public class MonitoredInputStream extends FilterInputStream {
private InputStream in;
private AtomicLong[] total;
public MonitoredInputStream(InputStream inputStream,AtomicLong... v) {
this.in=inputStream;
super(inputStream);
this.total=v;
}
@@ -1,15 +1,15 @@
package org.kne.cloud.network.klalb;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.atomic.AtomicLong;
public class MonitoredOutputStream extends OutputStream {
public class MonitoredOutputStream extends FilterOutputStream {
private OutputStream out;
private AtomicLong[] total;
public MonitoredOutputStream(OutputStream outputStream,AtomicLong ...v) {
this.out=outputStream;
super(outputStream);
this.total=v;
}
@@ -11,68 +11,49 @@ import java.util.concurrent.atomic.AtomicLong;
import org.kne.cloud.network.mport.FilterSocket;
public class MonitoredSocket extends FilterSocket {
public Monitor getMonitor() {
return monitor;
}
private static Timer t=new Timer("带宽测量线程",true);
private Monitor monitor;
private TimerTask ptt=new TimerTask() {
@Override
public void run() {
runMonitor();
runMonitor();
}
};
public MonitoredSocket(Socket socket) {
this(socket,new Monitor());
}
public MonitoredSocket(Socket socket,Monitor monitor) {
super(socket);
t.scheduleAtFixedRate(ptt, 1000, 1000);
this.monitor=monitor;
}
protected void runMonitor() {
inSpeed.set( inTraffic.get()-inTrafficOld.get());
outSpeed.set( outTraffic.get()-outTrafficOld.get());
inTrafficOld.set(inTraffic.get());
outTrafficOld.set(outTraffic.get());
monitor.updateSpeed();
}
public long getInTraffic() {
return inTraffic.get();
}
public long getOutTraffic() {
return outTraffic.get();
}
public long getInSpeed() {
return inSpeed.get();
}
public long getOutSpeed() {
return outSpeed.get();
}
private InputStream in;
private OutputStream out;
private AtomicLong inTraffic=new AtomicLong();
private AtomicLong outTraffic=new AtomicLong();
private AtomicLong inTrafficOld=new AtomicLong();
private AtomicLong outTrafficOld=new AtomicLong();
private AtomicLong inSpeed=new AtomicLong();
private AtomicLong outSpeed=new AtomicLong();
@Override
public InputStream getInputStream() throws IOException {
if(in==null)
in=new MonitoredInputStream(socket.getInputStream(), inTraffic);
in=new MonitoredInputStream(socket.getInputStream(), monitor.getInTrafficAL());
return in;
}
@Override
public OutputStream getOutputStream() throws IOException {
if(out==null) {
out=new MonitoredOutputStream(socket.getOutputStream(), outTraffic);
out=new MonitoredOutputStream(socket.getOutputStream(), monitor.getOutTrafficAL());
}
return out;
}
@@ -1,13 +1,41 @@
package org.kne.cloud.network.klalb;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class PINGPacket extends KLALBPacket {
private long time;
@Override
protected void writeToStream(DataOutput dto) throws IOException {
super.writeToStream(dto);
dto.writeLong(time);
}
public long getTime() {
return time;
}
@Override
protected void readFromStream(DataInput din) throws IOException {
super.readFromStream(din);
time=din.readLong();
}
@Override
public long getLength() {
return super.getLength()+8;
}
public PINGPacket() {
super(PING);
}
public PINGPacket(long time) {
super(PING);
this.time=time;
}
@Override
public String toString() {
return "PING";
@@ -1,12 +1,43 @@
package org.kne.cloud.network.klalb;
public class PONGPacket extends KLALBPacket {
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class PONGPacket extends KLALBPacket {
public long getTime() {
return time;
}
private long time;
@Override
protected void writeToStream(DataOutput dto) throws IOException {
super.writeToStream(dto);
dto.writeLong(time);
}
@Override
protected void readFromStream(DataInput din) throws IOException {
super.readFromStream(din);
time=din.readLong();
}
@Override
public long getLength() {
return super.getLength()+8;
}
public PONGPacket() {
super(PONG);
}
public PONGPacket(long time) {
super(PONG);
this.time=time;
}
@Override
public String toString() {
return "PONG";
}
public void redeltaTime(long delta) {
time+=delta;
}
}
@@ -18,7 +18,7 @@ public class RSTPacket extends KLALBPacket {
}
public RSTPacket() {
super();
super(RST);
}
public int getSport() {
@@ -26,7 +26,7 @@ public class SACKTPacket extends KLALBPacket {
}
public SACKTPacket() {
super();
super(SACKT);
}
@Override
@@ -21,7 +21,7 @@ public class SYNTPacket extends KLALBPacket {
}
public SYNTPacket() {
super();
super(SYNT);
}
@Override
+42 -20
View File
@@ -1,20 +1,33 @@
package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.NoRouteToHostException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;
public class SendTask extends TimerTask {
public class SendTask {
private int maxcount;
private int count;
private AtomicInteger count=new AtomicInteger();
private int priority;
private Inet6Address address;
private volatile long starttime=System.nanoTime();
private void resetTime() {
starttime=System.nanoTime();
}
private boolean checkTime(long limit) {
long curr=System.nanoTime();
boolean b=curr-starttime>limit;
if(b)
starttime=curr;
return b;
}
public SendTask( KLALBController controllker,Inet6Address address,DATATPacket kp,int priority,int maxcount) {
super();
this.maxcount = maxcount;
this.controllker = controllker;
this.kp = kp;
this.packet = kp;
this.address=address;
this.priority=priority;
}
@@ -28,13 +41,13 @@ public class SendTask extends TimerTask {
}
public DATATPacket getKp() {
return kp;
public DATATPacket getPacket() {
return packet;
}
private KLALBController controllker;
private DATATPacket kp;
private DATATPacket packet;
public int getMaxcount() {
@@ -43,25 +56,34 @@ public class SendTask extends TimerTask {
@Override
public void run() {
public void check(int number) throws IOException {
long limit= (1<<Math.min(4,count.get()-1))*(number<2?100:1000*number)*1000000L;
if(checkTime(limit))
run();
}
public void run() throws IOException {
if(count.get()>=maxcount) {
throw new IOException("send error!");
}
try {
if(count.get()==0) {
controllker.sendPacketToAddress((Inet6Address) address,
kp, priority+count);
packet, priority+count.get(),1);
}else {
controllker.sendPacketToAddress((Inet6Address) address,
packet, priority+count.get(),2);
}
} catch (NoRouteToHostException e) {
e.printStackTrace();
}
count++;
if(count>1) {
System.out.println("重传:"+kp);
}
if(count>=maxcount) {
cancel();
resetTime();
count.incrementAndGet();
if(count.get()>1) {
System.out.println(""+(count.get()-1)+"次重传:"+packet);
}
}
public void addToTimer(int timeout) {
controllker.getTimer().scheduleAtFixedRate(this, 0, timeout);
}
}
@@ -0,0 +1,58 @@
package org.kne.cloud.network.klalb;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Inet6Address;
import java.net.UnknownHostException;
import java.util.Properties;
import java.util.UUID;
public class ServerPropties extends Properties {
/**
*
*/
private static final long serialVersionUID = 1L;
public ServerPropties() throws IOException {
super();
load();
}
public void load() throws IOException {
File f=new File("kserver.ini");
if(!f.exists()||f.length()==0) {
f.createNewFile();
PrintStream ps=new PrintStream(f);
ps.println("virtualip="+ KLALBUtils.uuidToIP(UUID.randomUUID()).getHostAddress());
ps.println("bind=0.0.0.0:4568");
ps.println("local=127.0.0.1:25565");
ps.close();
}
FileReader fr = null;
try {
fr=new FileReader(f);
load(fr);
}finally {
if(fr!=null)
fr.close();
}
}
public Inet6Address getVirtualIP() {
try {
return (Inet6Address) Inet6Address.getByName((String) get("virtualip"));
} catch (UnknownHostException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return null;
}
public String getBind() {
return (String) get("bind");
}
public String getLocal() {
return (String) get("local");
}
}
@@ -0,0 +1,73 @@
package org.kne.cloud.network.klalb;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Scanner;
import org.kne.cloud.network.klalb.LineManager.LineEntry;
import org.kne.cloud.network.mport.MultipurposeSocketAddress;
import org.kne.cloud.network.mport.SocketBridge;
import org.kne.cloud.network.mport.TCPListener;
import org.kne.util.AutoProperties;
public class SimpleKLALBClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Scanner scn=new Scanner(System.in);
Properties def=new Properties();
def.setProperty("server", "");
def.setProperty("local", "");
AutoProperties ap=new AutoProperties(new File("klalbclient.ini"),def);
KLALBController kc=new KLALBController();
KLALBRemoteSocket kr=new KLALBRemoteSocket(new MultipurposeSocketAddress(ap.getProperty("server")).connectSocket());
kc.addRemoteSocket(kr);
kr.close();
System.out.println("连接成功:"+ap.getProperty("server"));
TCPListener tl=new TCPListener(new MultipurposeSocketAddress(ap.getProperty("local")));
tl.setCon((s)->{
KLALBVirtualSocket kvs=null;
try {
kvs=new KLALBVirtualSocket(kc, kr.getRemoteVaddr(), 23333);
new SocketBridge(s, kvs).run();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
if(kvs!=null)
try {
kvs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
tl.open();
System.out.println("提示:输入state并回车可以查看当前线路状态");
while(true) {
String s=scn.nextLine();
switch(s) {
case "state":
System.out.println("状态\t上传流量\t下载流量\t上传速度\t下载速度\t延迟\t抖动");
LineManager le=kc.getLineManager();
for (Iterator<java.util.Map.Entry<MultipurposeSocketAddress, LineEntry>> iterator = le.entrySet().iterator(); iterator.hasNext();) {
java.util.Map.Entry<MultipurposeSocketAddress, LineEntry> hostPort = iterator.next();
System.out.println(hostPort.getValue() .toString2());
//System.out.println();
}
break;
default :
System.out.println("未知命令!");
}
}
}
}
@@ -0,0 +1,180 @@
package org.kne.cloud.network.klalb;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import org.kne.cloud.network.klalb.LineManager.LineEntry;
import org.kne.cloud.network.mport.MultipurposeSocketAddress;
import org.kne.cloud.network.mport.Protocol;
import org.kne.cloud.network.mport.ProtocolDetectorServerSocketFactory;
import org.kne.cloud.network.mport.ProtocolDetectorSocket;
import org.kne.cloud.network.mport.ProxyProfileAnalyser;
import org.kne.cloud.network.mport.ProxyProfileExecutor;
import org.kne.cloud.network.mport.SocketBridge;
import org.kne.cloud.network.mport.TCPListener;
public class SimpleKLALBServer {
public static TCPListener tcpl,tcpl2;
public static ServerPropties sp;
public static KLALBController kc;
static {
MultipurposeSocketAddress.getServerSocketFactoryRegister().put("DETTCP", new ProtocolDetectorServerSocketFactory());
}
public static void main(String[] args) throws IOException {
System.out.println("KLALB负载均衡V2.0");
sp=new ServerPropties();
System.out.println("虚拟地址:"+sp.getVirtualIP().getHostAddress());
kc=new KLALBController(sp.getVirtualIP());
kc.setSelflineTableSupplier(()->{
return fileRead("linetable.txt");
});
kc.registerToProxyTypeAs("KLALB");
System.out.println("开放端口:"+sp.getBind());
openPort(sp.getBind());
System.out.println("本地服务:"+sp.getLocal());
openLocalPort(sp.getLocal());
Scanner scn=new Scanner(System.in);
while(true) {
String s=scn.next();
String[]sc=s.split(" ");
switch(sc[0]) {
case "help":
System.out.print("state:查看线路状态");
System.out.println("reload:重新加载线路配置");
break;
case "state":
LineManager le=kc.getLineManager();
for (Iterator<java.util.Map.Entry<MultipurposeSocketAddress, LineEntry>> iterator = le.entrySet().iterator(); iterator.hasNext();) {
java.util.Map.Entry<MultipurposeSocketAddress, LineEntry> hostPort = iterator.next();
System.out.println(hostPort.getValue() .toString());
}
break;
default:
System.out.println("未知命令,请输入help以查询指令说明");
}
}
}
private static void openPort(String bip) throws IOException {
if(tcpl!=null)
tcpl.close();
MultipurposeSocketAddress mpsa=new MultipurposeSocketAddress(bip,"DETTCP");
tcpl=new TCPListener(mpsa);
tcpl.setCon((soc)->{
ProtocolDetectorSocket pds=(ProtocolDetectorSocket) soc;
if(!pds.getProtocolStack().isEmpty()&&pds.getProtocolStack().pop().getName().equals("KLALB")) {
KLALBRemoteSocket krs=new KLALBRemoteSocket(pds);
kc.addRemoteSocket(krs);
}else {
MultipurposeSocketAddress mpsa2=new MultipurposeSocketAddress(sp.getLocal());
Socket s=null;
try {
s=mpsa2.connectSocket();
new SocketBridge(pds, s).run();
} catch (UnknownHostException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}finally {
if(s!=null)
try {
s.close();
} catch (IOException e1) {
// TODO 自动生成的 catch 块
e1.printStackTrace();
}
try {
soc.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
});
tcpl.open();
}
private static void openLocalPort(String bip) throws IOException {
if(tcpl2!=null)
tcpl2.close();
MultipurposeSocketAddress mpsa=new MultipurposeSocketAddress(bip);
tcpl2=new TCPListener(new MultipurposeSocketAddress("KLALB", "::0", 23333));
tcpl2.setCon((soc)->{
Socket s=null;
try {
s=mpsa.connectSocket();
new SocketBridge(soc, s).run();
} catch (UnknownHostException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}finally {
if(s!=null)
try {
s.close();
} catch (IOException e1) {
// TODO 自动生成的 catch 块
e1.printStackTrace();
}
try {
soc.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
});
tcpl2.open();
}
private static String fileRead(String filePath){
//1.定义一个BufferedReader对象,将文件内容读取到缓存
BufferedReader bufferedReader =null;
String returnInfo="";
try{
// 2.定义一个file对象
File file = new File(filePath);//定义一个file对象,用来初始化FileReader
// 3.定义一个fileReader对象
FileReader reader = new FileReader(file);
// 4.定义一个BufferedReader对象,将文件内容读取到缓存
bufferedReader = new BufferedReader(reader);
// 5.定义一个字符串缓存,将字符串存放缓存中
StringBuilder stringBuilder = new StringBuilder();
String str = "";
while ((str =bufferedReader.readLine()) != null) {//逐行读取文件内容,不读取换行符和末尾的空格
stringBuilder.append(str + "\n");//将读取的字符串添加换行符后累加存放在缓存中
}
returnInfo = stringBuilder.toString();
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if(bufferedReader!=null){
bufferedReader.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
return returnInfo;
}
}
@@ -17,12 +17,12 @@ public class VADDRPacket extends KLALBPacket {
}
public VADDRPacket() {
super();
super(VADDR);
}
@Override
public String toString() {
return "VADDR"+vaddr;
return "VADDR "+vaddr.getHostAddress();
}
@Override