JAVA は、単純な F5負荷分散 機能を実装します。
F5 負荷分散装置は非常に高価で起業家には不向きですが、HTTP サーバーの負荷分散機能を実装するための小さな純粋な JAVA コードであり、基本的な機能を使用できます。
ServerF5.java
package F5Server;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ServerF5 {
private int currentIndex = -1;// 最後に選択したサーバー
private int currentWeight = 0;// 現在のスケジュールの重み
private int maxWeight = 0; // 最大重量
private int gcdWeight = 0; //すべてのサーバーの重みの最大公約数
private int serverCount = 0; //サーバーの数
private List<Server> serverList; //サーバーコレクションList
private static ServerF5 context;
/**
* F5 コンテキストを初期化する
*/
public static ServerF5 getContext() {
if (context == null) {
context = new ServerF5();
}
return ServerF5.context;
}
/**
* 最大公約数を返します
*/
private static int gcd(int a, int b) {
BigInteger b1 = new BigInteger(String.valueOf(a));
BigInteger b2 = new BigInteger(String.valueOf(b));
BigInteger gcd = b1.gcd(b2);
return gcd.intValue();
}
/**
* すべてのサーバーの重みの最大公約数を返します
*/
private static int getGCDForServers(List<Server> serverList) {
int w = 0;
if (serverList.size() == 1) {
w = gcd(w, serverList.get(0).weight);
}
for (int i = 0, len = serverList.size(); i < len - 1; i++) {
if (w == 0) {
w = gcd(serverList.get(i).weight, serverList.get(i + 1).weight);
} else {
w = gcd(w, serverList.get(i + 1).weight);
}
}
return w;
}
/**
* すべてのサーバーの中で最大の重みを返します
*/
public static int getMaxWeightForServers(List<Server> serverList) {
int w = 0;
if (serverList.size() == 1) {
w = Math.max(w, serverList.get(0).weight);
}
for (int i = 0, len = serverList.size(); i < len - 1; i++) {
if (w == 0) {
w = Math.max(serverList.get(i).weight, serverList.get(i + 1).weight);
} else {
w = Math.max(w, serverList.get(i + 1).weight);
}
}
return w;
}
/**
* アルゴリズム処理:
* 一連のサーバーがあるとします。 S = {S0, S1, …, Sn-1}
* 対応する重みがあり、変数 currentIndex は最後に選択されたサーバーを示します。
* 重み currentWeight は 0 に初期化され、currentIndex は -1 に初期化され、初回の場合は最大の重みを持つサーバーが返されます,
* 重みを継続的に減少させながら、ポーリングが終了するまで重みが 0 に戻るまで、返す適切なサーバーを見つけます。
*/
public Server GetServer() {
while (true) {
currentIndex = (currentIndex + 1) % serverCount;
if (currentIndex == 0) {
currentWeight = currentWeight - gcdWeight;
if (currentWeight <= 0) {
currentWeight = maxWeight;
if (currentWeight == 0)
return null;
}
}
if (serverList.get(currentIndex).weight >= currentWeight) {
return serverList.get(currentIndex);
}
}
}
/*
* URLリストのF5プロパティを初期化します。
* */
public void init(List list) {
if (serverList != null) {
serverList.clear();
} else {
serverList = new ArrayList<Server>();
}
for (int i = 0; i < list.size(); i++) {
String url[] = list.get(i).toString().split(":");
String ip = url[0];
int port = Integer.parseInt(url[1]);
Server server = new Server(ip, 1, port);
serverList.add(server);
}
currentIndex = -1;
currentWeight = 0;
serverCount = serverList.size();
maxWeight = getMaxWeightForServers(serverList);
gcdWeight = getGCDForServers(serverList);
}
class Server {
public String ip;
public int weight;//現在のサーバーの重量
public int port;
public Server(String ip, int weight, int port) {
super();
this.ip = ip;
this.weight = weight;
this.port = port;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
/*
* テストして結果を確認する
* */
public static void main(String[] args) {
ServerF5 obj = new ServerF5();
List list = new ArrayList();
list.add("11.2.43.4:8080");
list.add("11.2.43.5:8081");
list.add("11.2.43.6:8082");
obj.init(list);
Map<String, Integer> countResult = new HashMap<String, Integer>();
for (int i = 0; i < 100; i++) {
Server s = obj.GetServer();
String log = "ip:" + s.ip + ";weight:" + s.weight;
if (countResult.containsKey(log)) {
countResult.put(log, countResult.get(log) + 1);
} else {
countResult.put(log, 1);
}
System.out.println(log);
}
for (Map.Entry<String, Integer> map : countResult.entrySet()) {
System.out.println("Server " + map.getKey() + " request count: " + map.getValue());
}
}
}
これは、基本的な F5 負荷分散アルゴリズムの実装クラスです,
F5 ロード バランシングの実際の呼び出しツール クラスを見てみましょう。
//ここでインポートする必要があります
httpcore-4.1.4.jar
httpclient-4.1.3.jar
ServerF5Utils.java
package F5Server;
import org.apache.http.HttpHost;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionRequest;
import org.apache.http.conn.ManagedClientConnection;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.protocol.BasicHttpContext;
import java.net.ConnectException;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
public class ServerF5Utils {
private static ServerF5Utils context;
private static List aliveUrlList;
private Timer timer;
private static ServerF5 serverF5;
static {
serverF5 = ServerF5.getContext();
}
public void updateAliveList(List urlLists) {
try {
//アクティブな URL リスト
aliveUrlList = new ArrayList();
//クライアント構成の URL のリスト。
for (int i = 0; i < urlLists.size(); i++) {
String[] urlport = urlLists.get(i).toString().split(":");
String ipaddr = urlport[0];
int port = Integer.parseInt(urlport[1]);
HttpClient httpClient = new DefaultHttpClient();
HttpRoute route = new HttpRoute(new HttpHost(ipaddr, port));
ClientConnectionRequest connRequest = httpClient.getConnectionManager().requestConnection(route, null);
ManagedClientConnection conn = connRequest.getConnection(10, TimeUnit.SECONDS);
try {
//クライアントが構成した URL リストを使用して接続を開きます。
conn.open(route, new BasicHttpContext(), new BasicHttpParams());
} catch (ConnectException e) {
System.out.println("AliveList init refuse:[" + ipaddr + ":" + port + "]");
continue;
}
if (conn.isOpen()) {
//テスト接続が成功すると、この接続はアクティブなリンクのリストに追加され ます。
aliveUrlList.add(urlLists.get(i).toString());
System.out.println("AliveList init Success:[" + this.aliveUrlList + "]");
conn.releaseConnection();
continue;
} else {
continue;
}
}
} catch (Exception e) {
System.out.println("HttpConnection Alive Url List init fail,please check Http URL,Exception:" + e.toString());
}
System.out.println("HttpConnection Alive Url List List =[" + aliveUrlList + "]");
//F5 サービスへのアクティブなリンクのリストを選択用に提供します。
serverF5.init(aliveUrlList);
}
/**
* アクティブな URL リンクがアルゴリズムによって選択されて返されます。
*/
public String getServerUrl() {
ServerF5.Server server = serverF5.GetServer();
String ip = server.getIp();
int port = server.getPort();
String url = ip + ":" + port;
return url;
}
/**
* ユーザーが呼び出せるように、F5 ツール クラスのコンテキスト環境を初期化します。
*/
public static ServerF5Utils getContext(final List urlLists) {
if (context == null) {
context = new ServerF5Utils();
context.updateAliveList(urlLists);
context.timer = new Timer();
context.timer.schedule(new TimerTask() {
@Override
public void run() {
context.updateAliveList(urlLists);
}
}, 50000, 300000);
}
return ServerF5Utils.context;
}
//Test
public static void main(String[] args) {
List<String> urls= new ArrayList<>();
urls.add("11.2.43.3:8080");
urls.add("11.2.43.4:8080");
urls.add("11.2.43.5:8080");
String shotUrl = ServerF5Utils.getContext(urls).getServerUrl();
System.out.println("shotUrl="+shotUrl);
}
}
テストおよび呼び出しメソッドは、サーバーによって構成された選択された URL のリストを F5 ツール クラス コンテキストに渡します。F5 ロード バランシングの初期化が成功した後、使用可能な選択された URL リンクを呼び出し元に返します。