JAVA implements a simple F5 load balancing function.

F5 load balancer is very expensive and not suitable for small entrepreneurial companies. Here is a small piece of pure JAVA code to implement the load balancing function of an HTTP server. It has basic load balancing functions and is enough for daily use.

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;// last selected server
    private int currentWeight = 0;// Current plan weight
    private int maxWeight = 0; // maximum weight
    private int gcdWeight = 0; //Greatest common divisor of all server weights
    private int serverCount = 0; //number of servers
    private List<Server> serverList; //List of server collections
    private static ServerF5 context;


     /**
     * Initialize the F5 context
     */
    public static ServerF5 getContext() {
        if (context == null) {
            context = new ServerF5();
        }
        return ServerF5.context;
    }

    /**
     * returns the greatest common divisor
     */
    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();
    }

    /**
     * Returns the greatest common divisor of all server weights
     */
    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;
    }

    /**
     * Returns the highest weight of all servers.
     */
    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;
    }

    /**
     * Algorithm processing:
       * Suppose we have a set of servers. S = {S0, S1, ..., Sn-1}
       * There is a corresponding weight, and the variable currentIndex indicates the last selected server.
       * Weight currentWeight is initialized to 0, currentIndex is initialized to -1, and the server with the largest weight is returned for the first time,
       * Find a suitable server to return, and keep reducing the weight until the weight returns to 0 after the polling ends.
     */
    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);
            }
        }
    }

    /*
    * Initializes the F5 property of the URL list.
    * */
    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;//current server 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;
        }
    }


    /*
    * Test and view results
    * */
    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());
        }
    }
}

This is the implementation class of the basic F5 load balancing algorithm,
Let’s take a look at the actual calling tool class of F5 load balancing.

//We need to import it here.
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 {
            //List of active URLs.
            aliveUrlList = new ArrayList();

            //List of client configuration URLs.
            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 {
                    //Open a connection using the client-configured list of URLs.
                    conn.open(route, new BasicHttpContext(), new BasicHttpParams());
                } catch (ConnectException e) {
                    System.out.println("AliveList init refuse:[" + ipaddr + ":" + port + "]");
                    continue;
                }

                if (conn.isOpen()) {
                //If the test connection is successful, the connection is added to the list of active links.
                    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 + "]");
        //List of active links offered to F5 services for selection.
        serverF5.init(aliveUrlList);
    }

    /**
     * Available URL links are algorithmically selected and returned.
     */
    public String getServerUrl() {
        ServerF5.Server server = serverF5.GetServer();
        String ip = server.getIp();
        int port = server.getPort();
        String url = ip + ":" + port;
        return url;
    }

    /**
     * Initializes the context of the F5 utility class so that the user can invoke it.
     */
    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);
    }
}

The Test and Invoke methods pass the server-built list of selected URLs to the F5 tool class context. After F5 Load Balancing initialization is successful, returns the selected URL link available to the caller.


发表回复

Thanks for your support to bet365fans!