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 servers = new ArrayList();
		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()方法,可以查看到控制台轮询选择了两个服务。

Ribbon负载均衡器详细介绍(七)_第1张图片

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

Ribbon负载均衡器详细介绍(七)_第2张图片

Ribbon负载均衡器详细介绍(七)_第3张图片

自定义负载均衡器的规则

参照上面的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 servers = lb.getAllServers();
		if(num>7){//返回8082端口服务
			return chooseServerByPort(servers,8082);
		}
		//返回8083端口服务
		return chooseServerByPort(servers,8083);
	}
	
	private Server chooseServerByPort(List 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 servers = new ArrayList();
		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负载均衡器详细介绍(七)_第4张图片

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负载均衡器详细介绍(七)_第5张图片

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。

源码点击这里

最后,大家有什么不懂的或者其他需要交流的内容,也可以进入我的QQ讨论群一起讨论:654331206

Spring Cloud系列:

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

Spring Boot的简单使用(二)

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

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

Spring Cloud之Eureka客户端健康检测(五)

Netflix之第一个Ribbon程序(六)

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

Spring Cloud中使用Ribbon(八)

具有负载均衡功能的RestTemplate底层原理(九)

OpenFeign之第一个Feign程序(十)

OpenFeign之feign使用简介(十一)

Spring Cloud中使用Feign(十二)

Netflix之第一个Hystrix程序(十三)

Netflix之Hystrix详细分析(十四)

Spring Cloud中使用Hystrix(十五)

Netflix之第一个Zuul程序(十六)

Spring Cloud集群中使用Zuul(十七)

Netflix之Zuul的进阶应用(十八)

消息驱动之背景概述(十九)

消息中间件之RabbitMQ入门讲解(二十)

消息中间件之Kafka入门讲解(二十一)

Spring Cloud整合RabbitMQ或Kafka消息驱动(二十二)

你可能感兴趣的:(Spring,Cloud)