Ribbon is a component responsible for load balancing in Spring Cloud Netflix family buckets. It is a collection of class libraries. Through Ribbon, programmers can use load balancing "transparently" without involving specific implementation details, without having to write too much code to implement load balancing in projects.
For example, in a cluster containing Eureka and Ribbon, a service (which can be understood as a jar package) is deployed on multiple servers. When multiple service users call the service at the same time, these concurrent requests can be forwarded to each server using a reasonable strategy.
In fact, when using various other components of Spring Cloud, we can see traces of Ribbon, such as Eureka can be integrated with Ribbon, and the Zuul component that provides gateway function can also be integrated with Ribbon when forwarding requests.
From the code level, Ribbon has the following three more important interfaces.
First, ILoadBalancer, which is also called a load balancer. Through it, we can reasonably forward requests in the project according to specific rules. The common implementation class is BaseLoadBalancer.
Second, IRule, this interface has multiple implementation classes, such as RandomRule and RoundRobinRule. These implementation classes specifically define load balancing strategies such as "random" and "polling", etc. We can also rewrite the methods in this interface to customize load balancing strategies.
In the BaseLoadBalancer class, we can set up load balancing policies through the IRule implementation class, so that the load balancer can reasonably forward requests based on this.
Third, the IPing interface, through this interface, we can obtain which servers are currently available, and we can also customize the rules to determine whether the server is available by rewriting the methods in this interface. In the BaseLoadBalancer class, we can also set policies to determine whether the server is available through the IPing implementation class.
1 ILoadBalancer: LoadBalancer interface
In Ribbon, we can also select servers based on specific load balancing policies through the ILOadBalancer interface.
Through the ILoadBalancerDemo.java below, let’s take a look at the basic usage of this interface. This class is placed in the RabbionBasicDemo project created in part 4.2, and the code is as follows.
//Omit the necessary package and import code public class ILoadBalancerDemo { public static void main(String[] args){ //Create the ILoadBalancer object ILoadBalancer loadBalancer = new BaseLoadBalancer(); //Define a server list List<Server> myServers = new ArrayList<Server>(); //Create two Server objects Server s1 = new Server("ekserver1",8080); Server s2 = new Server("ekserver2",8080); //Put two server objects into List type myServers object myServers.add(s1); myServers.add(s2); //Put myServers into the load balancer loadBalancer.addServers(myServers); //Initiate 10 calls in the for loop for(int i=0;i<10;i++){ //Use default load balancing rules to obtain Server type object Server s = loadBalancer.chooseServer("default"); //Output IP address and port number System.out.println(s.getHost() + ":" + s.getPort()); } } }In line 5, we create a loadBalancer object of type BaseLoadBalancer, and BaseLoadBalancer is the implementation class of the load balancer ILoadBalancer interface.
In lines 6 to 13, we create two Server-type objects and put them into myServers. In line 15, we put List-type myServers object into the load balancer.
In the for loop on lines 17 to 22, we simulated the server selection 10 times through the load balancer. Specifically, in line 19, we select the server with the default load balancing rules through the choiceServer method of loadBalancer. In line 21, we use the "print" action to simulate the actual "using Server object to handle requests" action.
The running results of the above code are as follows. We can see that the loadBalancer load balancer distributes 10 requests to 2 servers, and we can indeed see the effect of "load balancing".
Second, IRule, this interface has multiple implementation classes, such as RandomRule and RoundRobinRule. These implementation classes specifically define load balancing strategies such as "random" and "polling", etc. We can also rewrite the methods in this interface to customize load balancing strategies.
In the BaseLoadBalancer class, we can set up load balancing policies through the IRule implementation class, so that the load balancer can reasonably forward requests based on this.
Third, the IPing interface, through this interface, we can obtain which servers are currently available, and we can also customize the rules to determine whether the server is available by rewriting the methods in this interface. In the BaseLoadBalancer class, we can also set policies to determine whether the server is available through the IPing implementation class.
ekserver2:8080 ekserver1:8080 ekserver2:8080 ekserver1:8080 ekserver2:8080 ekserver1:8080 ekserver2:8080 ekserver1:8080 ekserver2:8080 ekserver1:8080 ekserver1:8080
2 IRule: Interface that defines load balancing rules
In Ribbon, we can set corresponding rules for the load balancer by defining the implementation class of the IRule interface. In the following table, we can see some commonly used implementation classes of the IRule interface.
The name of the implementation class | Load balancing rules |
RandomRule | Adopt a randomly selected strategy |
RoundRobinRule | Adopt a polling strategy |
RetryRule | When using this strategy, a retry action is included |
AvailabilityFilterRule | It will filter servers with multiple connection failures and excessive request concurrency |
WeightedResponseTimeRule | Set a weight for each server according to the average response time, and select servers with smaller average response time based on this weight value. |
ZoneAvoidanceRule | Priority is given to allocating the request to servers with the same zone as the request |
In the following IRuleDemo.java program, let’s take a look at the basic usage of IRule.
//Omit the necessary package and import code public class IRuleDemo { public static void main(String[] args){ //Please note that this is used for BaseLoadBalancer, not ILoadBalancer interface BaseLoadBalancer loadBalancer = new BaseLoadBalancer(); //Declare the load balancing policy based on polling IRule rule = new RoundRobinRule(); //Set the policy loadBalancer.setRule(rule); //Define 3 Servers as follows and put them in a collection of List type List<Server> myServers = new ArrayList<Server>(); Server s1 = new Server("ekserver1",8080); Server s2 = new Server("ekserver2",8080); Server s3 = new Server("ekserver3",8080); myServers.add(s1); myServers.add(s2); myServers.add(s3); //Set the server's List loadBalancer.addServers(myServers); //Output the result of load balancing for(int i=0;i<10;i++){ Server s = loadBalancer.chooseServer(null); System.out.println(s.getHost() + ":" + s.getPort()); } } }This code is very similar to the ILoadBalancerDemo.java in the above article, but there are the following differences.
1 In line 5, we define the load balancer through the BaseLoadBalancer class instead of the interface because the class contains the setRule method.
2 Define a rule object based on the polling rule in line 7 and set it into the load balancer in line 9.
3 In line 19, we put the List object containing 3 Servers into the load balancer, instead of the previous two. Since it is stored here for demonstration purposes, we will put in a "ekserver3" server that does not exist at all.
After running the program, we can see that there are 10 outputs, and it is indeed outputting the names of 3 servers in sequence according to the "polling" rule. If we change the code on line 7 to the following, we will see the server name "randomly" output.
IRule rule = new RandomRule();
3 IPing: The interface to determine whether the server is available
In the project, we usually let the ILoadBalancer interface automatically determine whether the server is available (these services are encapsulated in Ribbon's underlying code). In addition, we can also use the IPing interface in the Ribbon component to implement this function.
In the following IRuleDemo.java code, we will demonstrate the general usage of the IPing interface.
//Omit the necessary package and import code class MyPing implements IPing { public boolean isAlive(Server server) { //If the server name is ekserver2, return false if (server.getHost().equals("ekserver2")) { return false; } return true; } }The MyPing class defined in line 2 implements the IPing interface and overrides the isAlive method in line 3.
In this method, we judge based on the server name. Specifically, if the name is ekserver2, it returns false, which means that the server is unavailable, otherwise it returns true, which means that the current server is available.
public class IRuleDemo { public static void main(String[] args) { BaseLoadBalancer loadBalancer = new BaseLoadBalancer(); //Define the IPing object of IPing type IPing myPing = new MyPing(); //Use the myPing object loadBalancer.setPing(myPing); //Create three Server objects and put them in the load balancer List<Server> myServers = new ArrayList<Server>(); Server s1 = new Server("ekserver1", 8080); Server s2 = new Server("ekserver2", 8080); Server s3 = new Server("ekserver3", 8080); myServers.add(s1); myServers.add(s2); myServers.add(s3); loadBalancer.addServers(myServers); //Request the server multiple times through a for loop for (int i = 0; i < 10; i++) { Server s = loadBalancer.chooseServer(null); System.out.println(s.getHost() + ":" + s.getPort()); } } }In the main function in line 12, we create an IPing type myPing object in line 15, and put this object into the load balancer in line 17. Through the code on lines 18 to 26, we create three servers and put them into the load balancer as well.
In the for loop on line 28, we still request and output the server name. Since the load balancer here contains an IPing type object, after obtaining the server according to the policy, it will determine whether the server is available based on the isActive method in myPing.
Since in this method, we define that the server ekServer2 is not available, the load balancer loadBalancer object will never send the request to the server, that is, in the output result, we will not see the output of "ekserver2:8080".
From this we can see the general usage of the IPing interface. We can define the logic of "judging whether the server is available" by rewriting the isAlive method. In actual projects, the basis for judgment is nothing more than "whether the server responds for too long" or "whether the number of requests sent to the server is too many". These judgment methods are encapsulated in the IRule interface and its implementation class, so in general scenarios we use the IPing interface.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.