Ribbon负载均衡器详细介绍(七)

LoadBalancer的简单轮询规则

在上一篇博客中,我们使用Ribbon实现了负载,并且轮询请求了服务,我们就接着分析一下Ribbon里面实现负载均衡的LoadBalancer(负载均衡器),去看看它底层是怎么做的,以及这些请求规则如何配置。

首先拿到我们上一篇博客中的ribbon-client项目,在com.init.springCloud包下新建LoadBalancerTest类,在这个类里面新建一个基础的Ribbon负载均衡器,然后创建一个服务列表,并把服务列表装载到基础负载均衡器里,之后让负载均衡器多次执行选择服务,我们通过输出服务信息查看它的选取规则:

package com.init.springCloud;

import java.util.ArrayList;
import java.util.List;

import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

public class LoadBalancerTest {

	public static void main(String[] args) {
		ILoadBalancer loadBalancer = new BaseLoadBalancer();
		List<Server> servers = new ArrayList<Server>();
		servers.add(new Server("localhost",8082));
		servers.add(new Server("localhost",8083));
		loadBalancer.addServers(servers);
		for(int i=0; i<10; i++){
			//参数是负载均衡器可用来确定要返回哪个服务器的对象。置空表示不使用
			Server chosedServer = loadBalancer.chooseServer(null);
			System.out.println("选择的服务是:"+chosedServer);
			
		}
	}
	
}

运行LoadBalancerTest的main()方法,可以查看到控制台轮询选择了两个服务。


通过跟踪LoadBalancer的chooseServer方法,我们可以查看到负载均衡器默认使用的是RoundRobinRule



自定义负载均衡器的规则

参照上面的RoundRobinRule,我们也实现IRule接口,来创建一个自己的规则,在com.init.springCloud包下新建MyRule类,实现IRule接口,编写一个出现8082端口服务概率为20%的规则类:

package com.init.springCloud;

import java.util.List;
import java.util.Random;

import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server;

public class MyRule implements IRule {

	private ILoadBalancer lb;
	
	@Override
	public Server choose(Object key) {
		Random random = new Random();
		Integer num = random.nextInt(10);//在0-9这10个随机数里取值
		//获取传输负载均衡器里所有的服务
		List<Server> servers = lb.getAllServers();
		if(num>7){//返回8082端口服务
			return chooseServerByPort(servers,8082);
		}
		//返回8083端口服务
		return chooseServerByPort(servers,8083);
	}
	
	private Server chooseServerByPort(List<Server> servers,Integer port){
		for (Server server : servers) {
			if(server.getPort() == port){
				return server;
			}
		}
		return null;
	}

	@Override
	public void setLoadBalancer(ILoadBalancer lb) {
		this.lb = lb;
	}

	@Override
	public ILoadBalancer getLoadBalancer() {
		return lb;
	}

}

之后再创建一个类MyRuleTest,让负载均衡器加载我们新建的规则类,实现我们自己的负载,内容和LoadBalancerTest类大致:

package com.init.springCloud;

import java.util.ArrayList;
import java.util.List;

import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;

public class MyRuleTest {

	public static void main(String[] args) {
		
		BaseLoadBalancer loadBalancer = new BaseLoadBalancer();
		
		MyRule myRule = new MyRule();
		loadBalancer.setRule(myRule);
		
		List<Server> servers = new ArrayList<Server>();
		servers.add(new Server("localhost",8082));
		servers.add(new Server("localhost",8083));
		
		loadBalancer.addServers(servers);
		
		for(int i=0; i<10; i++){
			//参数是负载均衡器可用来确定要返回哪个服务器的对象。置空表示不使用
			Server chosedServer = loadBalancer.chooseServer(null);
			System.out.println("选择的服务是:"+chosedServer);
			
		}
		
	}
	
}

运行MyRuleTest的main()方法,可以看到负载均衡器选择8082端口的概率就变小了


Ribbon的组件可以用编程方式设置,也可以是客户端配置属性的一部分,并通过反射创建。这些相关的属性在配置文件里面需要以"客户端名称"."命名空间"."属性名"的方式实现。Ribbon提供了以下属性的设置:

  1. NFLoadBalancerClassName  负载均衡器类名称设置
  2. NFLoadBalancerRuleClassName  规则类名称设置
  3. NFLoadBalancerPingClassName  Ping类名称设置
  4. NIWSServerListClassName  服务列表类名称设置
  5. NIWSServerListFilterClassName  服务列表过滤器名称设置

我们为了验证创建的自定义规则能否生效,使用上面的配置方法去修改ribbon-client项目的RibbonTest类,增加一行配置自定义负载均衡器规则的代码,RibbonTest类最新代码:

package com.init.springCloud;

import com.netflix.client.ClientException;
import com.netflix.client.ClientFactory;
import com.netflix.client.http.HttpRequest;
import com.netflix.client.http.HttpResponse;
import com.netflix.config.ConfigurationManager;
import com.netflix.niws.client.http.RestClient;

public class RibbonTest {

	public static void main(String[] args) {
		
		//设置要请求的服务器
		ConfigurationManager.getConfigInstance().setProperty(
	      		"sample-client.ribbon.listOfServers", 
	      		"localhost:8082,localhost:8083");
		//配置自定义的负载均衡器规则
		ConfigurationManager.getConfigInstance().setProperty(
	      		"sample-client.ribbon.NFLoadBalancerRuleClassName", 
	      		MyRule.class.getName());
		//设置REST请求客户端
		RestClient client = (RestClient) ClientFactory.getNamedClient("sample-client");
		//创建请求实例
		HttpRequest request = HttpRequest.newBuilder().uri("/search/1").build();
		//连续发送10次请求到服务器
		for(int i=0; i<10; i++){
			try {
				HttpResponse response = client.executeWithLoadBalancer(request);
				String result = response.getEntity(String.class);
				System.out.println("请求结果:"+result);
			} catch (ClientException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
	}
	
}

之后启动ribbon-server,在控制台键入两个端口8082和8083,运行两个不同的服务实例,再回来运行ribbon-client项目RibbonTest的main()方法,可以看到控制台输出的结果,证明我们配置的规则类成功了。


Ribbon内置的规则

  1. AvailabilityFilteringRule: 这条规则将跳过被认为是“电路跳闸”的服务器或具有高并发连接数的服务器。
  2. BestAvailableRule:这个规则会跳过“电路跳闸”的服务器,然后选取一个并发请求数最低的服务。
  3. PredicateBasedRule:将服务器过滤逻辑委托给{@link AbstractServerPredicate}实例的规则。过滤后,服务器会以循环的方式从过滤列表中返回。
  4. RandomRule:一种随机分配流量的负载平衡策略。
  5. RetryRule:在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server。
  6. RoundRobinRule:这条规则简单地通过轮询来选择服务器。它通常被用作更高级规则的默认规则或后退。
  7. WeightedResponseTimeRule:对于这个规则,每个服务器根据其平均响应时间给定一个权重。响应时间越长,得到的权重就越小。规则随机选择一个服务器,其中的可能性由服务器的权重决定。
  8. ZoneAvoidanceRule:使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。

常用的一些规则我用蓝色字体凸显出来了,其实大部分规则底层使用的都是RoundRobinRule。

源码点击这里

Spring Cloud系列:

Spring Cloud介绍与环境搭建(一)

Spring Boot的简单使用(二)

Spring Cloud服务管理框架Eureka简单示例(三)

Spring Cloud服务管理框架Eureka项目集群(四)

猜你喜欢

转载自blog.csdn.net/mrspirit/article/details/80203414
今日推荐