一、代碼實現
詳見 我的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); | ||
} | ||
} |