Ribbon是Spring Cloud的一个组件, 是基于Netflix Ribbon实现的一套客户端负载均衡工具它可以让我们使用一个注解就能轻松的搞定负载均衡。

  • Ribbon是Netlix发布的开源项目,主要功能是提供客户端的软件负载均衡算法服务调用
  • Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。
  • 简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。
  • 开发者会很容易使用Ribbon实现自定义的负载均衡算法。


一、修改IndexApplication类:

1、在RestTemplate Bean方法上添加 @LoadBalanced 注解,启用Ribbon负载均衡功能;

2、添加RestTemplateCustomizer Bean,注入一个自定义拦截器 CustomRestTemplateInterceptor 输出当前访问的微服务实例URL,测试负载均衡是否成功;   

3、启动类没加@EnableDiscoveryClient注解,其实这个注解在新版本后都不用显示加入,因为已经默认


package com.temp.index;
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
import com.temp.index.utils.CustomRestTemplateInterceptor;

@SpringBootApplication
public class IndexApplication {
	public static void main(String[] args) {
		SpringApplication.run(IndexApplication.class, args);
	}

	@Bean
	@LoadBalanced
	public RestTemplate getRestTemplate() {
		return new RestTemplate();
	}

	@Bean
	public RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) {
		RestTemplateCustomizer rtc = new RestTemplateCustomizer() {
			@Override
			public void customize(RestTemplate restTemplate) {
				List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());
				list.add(loadBalancerInterceptor);
				list.add(new CustomRestTemplateInterceptor());
				restTemplate.setInterceptors(list);
			}
		};
		return rtc;
	}
}


package com.temp.index.utils;
import java.io.IOException;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

public class CustomRestTemplateInterceptor implements ClientHttpRequestInterceptor {
	@Override
	public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
		System.out.println("本次请求的服务URL:" + request.getURI());
		return execution.execute(request, body);
	}
}


二、修改IndexController服务请求方法:


package com.temp.index.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.client.RestTemplate;

@Controller
public class IndexController {
	@Autowired
	private RestTemplate restTemplate;

	@GetMapping({ "", "/" })
	public String index(Model m) {
		// 通过restTemplate,直接使用服务名调用用户微服务
		Object obj = restTemplate.getForObject("http://nacos-user/user/2", String.class);
		m.addAttribute("test", obj);
		return "index";
	}
}

刷新访问,输出结果如下:


三、Ribbon内置了多种负载均衡策略,内部负载均衡的顶级接口为 com.netflix.loadbalancer.IRule , 具体的负载策略如下图所示:

策略名策略描述实现说明

BestAvailableRule

选择一个最小的并发请求的server

逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server

AvailabilityFilteringRule

过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections超过配置的阈值)

使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态

WeightedResponseTimeRule

根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。

一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权   重。当刚开始运行,没有形成statas时,使用roubine策略选择server。

RetryRule

对选定的负载均衡策略机上重试机制。

在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server


RoundRobinRule

轮询方式轮询选择server

轮询index,选择index对应位置的server


RandomRule

随机选择一个server

在index上随机,选择index对应位置的server

ZoneAvoidanceRule

复合判断server所在区域的性能和server 的可用性选择server

使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。


1、默认为轮询策略:

所以看上面的输出结果是有顺序的


2、通过设置IRule Bean来修改Ribbon的负载均衡策略,在IndexApplication启动类添加如下代码:

@Bean
public IRule irule() {
	return new RandomRule();// 实现随机的负载均衡策略
}

3、通过bootstrap.properties 文件添加配置设置负载均衡策略:


nacos-user.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule



其中nacos-user为服务名。