一、代码实现
详见 我的github:https://github.com/sunxiaoning90/com_live_test
二、测试结果
10次访问
1W次访问
package com.live.test.api.core.serverloadbalance.routeAcc; | ||
import java.util.Iterator; | ||
import java.util.Map; | ||
import java.util.Map.Entry; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import com.alibaba.fastjson.JSONArray; | ||
import com.alibaba.fastjson.JSONObject; | ||
/** | ||
* 路由访问 对象 | ||
* | ||
* @author live | ||
* @2019年12月9日 @下午2:46:59 | ||
*/ | ||
public class RouteAcc { | ||
private Map<String, RouteNodeAcc> accMap;// route:routeNodeAcc | ||
private String route;// 路由 module.service.method | ||
private String keepCountRouteNode;// 连续命中最大值是哪个路由节点 module.service.method.server | ||
private long keepCount;// 连续命中最大值 | ||
private long count;// 命中总数 | ||
private String last;// 最后一次命中哪个路由节点:module.service.method.server | ||
private RouteAcc() { | ||
this.accMap = new ConcurrentHashMap<String, RouteNodeAcc>(); | ||
} | ||
public RouteAcc(String route) { | ||
this(); | ||
this.setRoute(route); | ||
} | ||
public String getRoute() { | ||
return route; | ||
} | ||
public void setRoute(String abc) { | ||
this.route = abc; | ||
} | ||
public String getLast() { | ||
return last; | ||
} | ||
public void setLast(String last) { | ||
this.last = last; | ||
} | ||
public void put(String route) { | ||
this.incrementCount(); | ||
RouteNodeAcc acc; | ||
if (!this.accMap.containsKey(route)) { | ||
acc = new RouteNodeAcc(route); | ||
this.accMap.put(route, acc); | ||
} else { | ||
acc = this.accMap.get(route); | ||
} | ||
acc.incrementCount(); | ||
if (route.equals(this.getLast())) { | ||
acc.incrementKeepCountTmp(); | ||
} else { | ||
this.setLast(route);// 设置最后一次访问 | ||
accMap.get(route).setKeepCountTmpReset(); | ||
} | ||
if (acc.getKeepCount() > this.getKeepCount()) {// 设置命中最大值 | ||
this.setKeepCountAbcd(acc.getRouteNode()); | ||
this.setKeepCount(acc.getKeepCount()); | ||
} | ||
} | ||
public String getKeepCountRouteNode() { | ||
return keepCountRouteNode; | ||
} | ||
public void setKeepCountAbcd(String keepCount) { | ||
this.keepCountRouteNode = keepCount; | ||
} | ||
public long getKeepCount() { | ||
return keepCount; | ||
} | ||
public void setKeepCount(long keepCount) { | ||
this.keepCount = keepCount; | ||
} | ||
public long getCount() { | ||
return count; | ||
} | ||
public void setCount(long count) { | ||
this.count = count; | ||
} | ||
public void incrementCount() { | ||
this.setCount(this.getCount() + 1); | ||
} | ||
public JSONObject toJson() { | ||
JSONObject json = new JSONObject(); | ||
json.put("route(路由)", this.getRoute()); | ||
json.put("count(命中总数)", this.getCount()); | ||
json.put("keepCountRouteNode(最高连续命中路由节点)", this.getKeepCountRouteNode()); | ||
json.put("keepCount(最高连续命中计数器)", this.getKeepCount()); | ||
JSONArray accArray = new JSONArray(); | ||
Iterator<Entry<String, RouteNodeAcc>> iterator = this.accMap.entrySet().iterator(); | ||
while (iterator.hasNext()) { | ||
Entry<String, RouteNodeAcc> next = iterator.next(); | ||
JSONObject accJson = new JSONObject(); | ||
accJson.put(next.getKey(), next.getValue().toJson()); | ||
accArray.add(accJson); | ||
} | ||
json.put("routeNodeAcc", accArray); | ||
return json; | ||
} | ||
} |
74 ...core/src/main/java/com/live/test/api/core/serverloadbalance/routeAcc/RouteAccManager.java
@@ -0,0 +1,74 @@ | ||
package com.live.test.api.core.serverloadbalance.routeAcc; | ||
import java.util.Date; | ||
import java.util.Iterator; | ||
import java.util.Map; | ||
import java.util.Map.Entry; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import com.alibaba.fastjson.JSONArray; | ||
import com.alibaba.fastjson.JSONObject; | ||
/** | ||
* 路由访问管理 | ||
* | ||
* @author live | ||
* @2019年12月3日 @上午11:01:56 | ||
*/ | ||
public class RouteAccManager { | ||
/** | ||
* 路由访问记录: k:v键值对 route: routeAcc | ||
*/ | ||
private Map<String, RouteAcc> accPoMap = new ConcurrentHashMap<String, RouteAcc>(); | ||
private Date date; | ||
private RouteAccManager() { | ||
setDate(new Date()); | ||
} | ||
public static RouteAccManager getInstance() { | ||
return SingletonHolder.instance; | ||
} | ||
private static class SingletonHolder { | ||
private static RouteAccManager instance = new RouteAccManager(); | ||
} | ||
public void put(String routeNode) { | ||
String route = routeNode.substring(0, routeNode.lastIndexOf(".")); | ||
if (!this.accPoMap.containsKey(route)) { | ||
this.accPoMap.put(route, new RouteAcc(route)); | ||
} | ||
RouteAcc accPo = this.accPoMap.get(route); | ||
accPo.put(routeNode); | ||
} | ||
public Date getDate() { | ||
return date; | ||
} | ||
public void setDate(Date date) { | ||
this.date = date; | ||
} | ||
@SuppressWarnings("deprecation") | ||
public JSONObject toJson() { | ||
JSONObject json = new JSONObject(); | ||
json.put("date(开始时间)", this.getDate().toLocaleString()); | ||
JSONArray routeAccArray = new JSONArray(); | ||
Iterator<Entry<String, RouteAcc>> iterator = this.accPoMap.entrySet().iterator(); | ||
while (iterator.hasNext()) { | ||
Entry<String, RouteAcc> next = iterator.next(); | ||
JSONObject routeAcc = new JSONObject(); | ||
routeAcc.put(next.getKey(), next.getValue().toJson()); | ||
routeAccArray.add(routeAcc); | ||
} | ||
json.put("routeAccs", routeAccArray); | ||
return json; | ||
} | ||
} |
81 ...pi_core/src/main/java/com/live/test/api/core/serverloadbalance/routeAcc/RouteNodeAcc.java
@@ -0,0 +1,81 @@ | ||
package com.live.test.api.core.serverloadbalance.routeAcc; | ||
import com.alibaba.fastjson.JSONObject; | ||
/** | ||
* 路由节点访问 对象 | ||
* | ||
* @author live | ||
* @2019年12月10日 @下午3:26:43 | ||
*/ | ||
public class RouteNodeAcc { | ||
private String routeNode;// 路由节点 module.service.method.server | ||
private long keepCount;// 最高连续命中计数器 | ||
private long count;// 命中总数数计数器 | ||
private long keepCountTmp;// 临时连续命中计数器,当 临时连续命中计数器 大于 最高连续命中计数器时,刷新 最高连续命中计数器 | ||
private RouteNodeAcc() { | ||
} | ||
public RouteNodeAcc(String routeNode) { | ||
this(); | ||
this.setRouteNode(routeNode); | ||
} | ||
public String getRouteNode() { | ||
return routeNode; | ||
} | ||
public void setRouteNode(String routeNode) { | ||
this.routeNode = routeNode; | ||
} | ||
public long getKeepCountTmp() { | ||
return keepCountTmp; | ||
} | ||
public void setKeepCountTmp(long keepCountTmp) { | ||
this.keepCountTmp = keepCountTmp; | ||
if (keepCountTmp > this.getKeepCount()) {// 当 临时连续命中计数器 大于 最高连续命中计数器时,刷新 最高连续命中计数器 | ||
this.setKeepCount(keepCountTmp); | ||
} | ||
} | ||
public void incrementCount() { | ||
this.setCount(this.getCount() + 1); | ||
} | ||
public long getKeepCount() { | ||
return keepCount; | ||
} | ||
public void setKeepCount(long keepCount) { | ||
this.keepCount = keepCount; | ||
} | ||
public long getCount() { | ||
return count; | ||
} | ||
public void setCount(long count) { | ||
this.count = count; | ||
} | ||
public void setKeepCountTmpReset() { | ||
this.setKeepCountTmp(0); | ||
} | ||
public void incrementKeepCountTmp() { | ||
this.setKeepCountTmp(this.getKeepCountTmp() + 1); | ||
} | ||
public JSONObject toJson() { | ||
JSONObject json = new JSONObject(); | ||
json.put("routeNode(路由节点)", routeNode); | ||
json.put("count(命中总数数计数器)", count); | ||
json.put("keepCountTmp(临时连续命中计数器)", keepCountTmp); | ||
json.put("keepCount(最高连续命中计数器)", keepCount); | ||
return json; | ||
} | ||
} |
36 ..._core/src/main/java/com/live/test/api/core/serverloadbalance/serverdispatcher/Client.java
@@ -0,0 +1,36 @@ | ||
package com.live.test.api.core.serverloadbalance.serverdispatcher; | ||
import com.live.test.api.core.serverloadbalance.serverdispatcher.impl.PollServerDispatcher; | ||
public class Client { | ||
public static void main(String[] args) { | ||
new Client().test1(); | ||
} | ||
private void test1() { | ||
int min = 1; | ||
int max = 5; | ||
IServerDispatcher sd = new PollServerDispatcher(min, max); | ||
new java.lang.Thread(new Runnable() { | ||
@Override | ||
public void run() { | ||
for (int i = 1; i <= 10; i++) { | ||
testGetNext(sd); | ||
} | ||
} | ||
}).start(); | ||
for (int i = 1; i <= 10; i++) { | ||
testGetNext(sd); | ||
} | ||
} | ||
private void testGetNext(IServerDispatcher sd) { | ||
// int next = sd.getNext(); | ||
// long count = sd.getCount(); | ||
// int last = sd.getLast(); | ||
// System.out.println("count:" + count + ",last:" + last + ",next:" + next); | ||
} | ||
} |
34 ...ain/java/com/live/test/api/core/serverloadbalance/serverdispatcher/IServerDispatcher.java
@@ -0,0 +1,34 @@ | ||
package com.live.test.api.core.serverloadbalance.serverdispatcher; | ||
public interface IServerDispatcher { | ||
/** | ||
* 初始化最小值 | ||
* @return | ||
*/ | ||
void setMin(int min); | ||
/** | ||
* 初始化最大值 | ||
* @return | ||
*/ | ||
void setMax(int max); | ||
/** | ||
* 最后一次取值 | ||
* @return | ||
*/ | ||
int getLast(); | ||
/** | ||
* 下一次取值 | ||
* @return | ||
*/ | ||
int getNext(); | ||
/** | ||
* 自启动后,访问过多少次 | ||
* @return | ||
*/ | ||
long getCount(); | ||
} |
72 .../live/test/api/core/serverloadbalance/serverdispatcher/impl/KeepLastServerDispatcher.java
@@ -0,0 +1,72 @@ | ||
package com.live.test.api.core.serverloadbalance.serverdispatcher.impl; | ||
import com.live.test.api.core.serverloadbalance.serverdispatcher.IServerDispatcher; | ||
/** | ||
* 负载均衡-每次获取上一次的路由: | ||
* @author live | ||
* @2019年12月10日 @下午12:22:38 | ||
*/ | ||
public class KeepLastServerDispatcher implements IServerDispatcher { | ||
private int max; // max 和 min必须填写 | ||
private int min; | ||
private int last; | ||
private long count = 0;//自启动后,访问过多少次 | ||
public KeepLastServerDispatcher() { | ||
} | ||
public KeepLastServerDispatcher(int min, int max) { | ||
this(); | ||
this.setMin(min); | ||
this.setMax(max); | ||
} | ||
public int getMax() { | ||
return max; | ||
} | ||
public int getMin() { | ||
return min; | ||
} | ||
@Override | ||
public void setMin(int min) { | ||
this.min = min; | ||
} | ||
@Override | ||
public void setMax(int max) { | ||
this.max = max; | ||
} | ||
@Override | ||
public int getLast() { | ||
return this.last; | ||
} | ||
@Override | ||
public synchronized int getNext() { | ||
return this.getLast(); | ||
} | ||
public void setLast(int last) { | ||
this.last = last; | ||
} | ||
public long getCount() { | ||
return count; | ||
} | ||
public void setCount(long count) { | ||
this.count = count; | ||
} | ||
public void incrementCount() { | ||
this.setCount(this.getCount()+1); | ||
} | ||
} |
88 .../com/live/test/api/core/serverloadbalance/serverdispatcher/impl/PollServerDispatcher.java
@@ -0,0 +1,88 @@ | ||
package com.live.test.api.core.serverloadbalance.serverdispatcher.impl; | ||
import com.live.test.api.core.serverloadbalance.serverdispatcher.IServerDispatcher; | ||
/** | ||
* 负载均衡-轮询获取路由:1,2,3,1,2,3... | ||
* @author live | ||
* @2019年12月10日 @下午12:22:38 | ||
*/ | ||
public class PollServerDispatcher implements IServerDispatcher { | ||
private int max; // max 和 min必须填写 | ||
private int min; | ||
private int last; | ||
private long count = 0;//自启动后,访问过多少次 | ||
private PollServerDispatcher() { | ||
} | ||
public PollServerDispatcher(int min, int max) { | ||
this(); | ||
this.setMin(min); | ||
this.setMax(max); | ||
} | ||
public int getMax() { | ||
return max; | ||
} | ||
public int getMin() { | ||
return min; | ||
} | ||
@Override | ||
public void setMin(int min) { | ||
this.min = min; | ||
} | ||
@Override | ||
public void setMax(int max) { | ||
this.max = max; | ||
} | ||
@Override | ||
public int getLast() { | ||
return this.last; | ||
} | ||
@Override | ||
public synchronized int getNext() { | ||
int next ;// 取值 | ||
if(this.getCount() == 0) {// 第一次取值取最小值 | ||
next = this.getMin(); | ||
}else { | ||
next = this.getLast() + 1; | ||
} | ||
if (next > this.getMax()) {// 若取值小于最小值,取最小值 | ||
next = this.getMin(); | ||
} else if (next < this.getMin()) {// 若取值小于最小值,取最小值 | ||
next = this.getMin(); | ||
} | ||
System.out.println("上一次概况:count:" + this.getCount() + ",last:" + this.getLast()+",next:" + next); | ||
this.setLast(next);// 刷新 last | ||
this.incrementCount();//刷新总数 | ||
return next; | ||
} | ||
public void setLast(int last) { | ||
this.last = last; | ||
} | ||
public long getCount() { | ||
return count; | ||
} | ||
public void setCount(long count) { | ||
this.count = count; | ||
} | ||
public void incrementCount() { | ||
this.setCount(this.getCount()+1); | ||
} | ||
} |