目录

  • `Ribbon` 简介
  • 服务器端负载均衡
  • 客户端负载均衡
  • 服务器端负载均衡 `VS` 客户端负载均衡
  • `Ribbon` 实现客户端负载均衡
  • 服务提供方 `Controller` 层
  • 服务消费方引入依赖
  • `Ribbon` 实现负载均衡
  • 方式一
  • 方式二
  • `Ribbon` 负载均衡的策略
  • `Ribbon` 的重试机制设置
  • `Ribbon`工作流程
  • 服务发现
  • 服务选择
  • 服务监听


Ribbon 简介

  • RibbonNetflix 发布的开源项目,主要功能是提供客户端的软件负载均衡算法,是一个基于 HTTPTCP 的客户端负载均衡工具
  • springCloudRibbon 做了二次封装,可以让我们使用 RestTemplate 的服务请求,自动转换成客户端负载均衡的服务调用
  • Ribbon 支持多种负载均衡算法,还支持自定义的负载均衡算法
  • Ribbon 只是一个工具类框架,比较小巧,springCloud 对它封装后使用也非常方便,它不像服务注册中心、配置中心、API 网关那样需要独立部署,Ribbon 只需要在代码直接使用即可

服务器端负载均衡

负载均衡是我们处理高并发、缓解网络压力和进行服务器扩容的重要手段之一,但是一般情况下我们所说的负载均衡通常都是指服务器端负载均衡,服务器端负载均衡又分为两种,一种是硬件负载均衡,还有一种是软件负载均衡

  • 硬件负载均衡主要通过在服务器节点之前安装专门用于负载均衡的设备,常见的如:F5
  • 软件负载均衡则主要是在服务器上安装一些具有负载均衡功能的软件来完成请求分发进而实现负载均衡,常见的如:LVS 、 Nginx 、Haproxy

无论是硬件负载均衡还是软件负载均衡,它的工作原理都不外乎下面这张图

tibco的daemon是什么 tibbon_tibco的daemon是什么

客户端负载均衡

而微服务的出现,则为负载均衡的实现提供了另外一种思路:把负载均衡的功能以库的方式集成到服务的消费方,而不再是由一台指定的负载均衡设备集中提供。这种方案称为软负载均衡或者客户端负载均衡。常见的如:springCloud 中的 Ribbon

Ribbon 是一个基于 HTTPTCP 的客户端负载均衡器,当我们将 RibbonEureka 一起使用时,Ribbon 会到 Eureka 注册中心去获取服务端列表,然后进行轮询等方式访问以到达负载均衡的作用,客户端负载均衡也需要心跳机制去维护服务端清单的有效性,当然这个过程需要配合服务注册中心一起完成

springCloud 中,Ribbon 主要与 RestTemplate 对象配合起来使用,Ribbon 会自动化配置 RestTemplate 对象,通过 @LoadBalanced 开启 RestTemplate 对象调用时的负载均衡

服务器端负载均衡 VS 客户端负载均衡

  • 服务器端负载均衡:客户端先发送请求到负载均衡服务器,然后由负载均衡服务器通过负载均衡算法,在众多可用的服务器之中选择一个来处理请求
  • 客户端负载均衡:客户端自己维护一个可用服务器地址列表,在发送请求前先通过负载均衡算法选择一个将用来处理本次请求的服务器,然后再直接将请求发送至该服务器

Ribbon 实现客户端负载均衡

服务提供方 Controller

@RestController
@RequestMapping("/api/v1/msg")
public class MessageController {
 
	@Value("${server.port}")
	private String port;
 
	@GetMapping("/get")
	public String getMsg() {
		return "This message is sent from port: " + port;
	}
}

服务消费方引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

Ribbon 实现负载均衡

在启动类中向 spring 容器中注入一个带有 @LoadBalanced 注解的 RestTemplatebean

@SpringBootApplication
@EnableEurekaClient
public class MessageCenterApplication {
 
	@Bean
	@LoadBalanced
	public RestTemplate restTemplate() { 
		return new RestTemplate();
	}
 
	public static void main(String[] args) {
		SpringApplication.run(MessageCenterApplication.class, args);
	}
}

方式一

@RestController
@RequestMapping("/api/v1/center")
public class MessageCenterController {
 
	@Autowired
	private RestTemplate restTemplate;
 
	@GetMapping("/msg/get")
	public Object getMsg() {
		String msg = restTemplate.getForObject("http://message-service/api/v1/msg/get", String.class);
		return msg;
	}
}

方式二

直接使用 LoadBalancerClient 中的负载均衡策略获取一个可用的服务地址,然后再进行请求

@RestController
@RequestMapping("/api/v1/center")
public class MessageCenterController {
 
	@Autowired
	private LoadBalancerClient loadBalancer;
 
	@GetMapping("/msg/get")
	public Object getMsg() {
		ServiceInstance instance = loadBalancer.choose("message-service");
		URI url = URI.create(String.format("http://%s:%s/api/v1/msg/get", instance.getHost(), instance.getPort()));
		String msg = restTemplate.getForObject(url, String.class);
		return msg;
	}
}

待应用启动之后,连续三次请求地址 http://localhost:8781/api/v1/center/msg/get ,返回的结果如图所示

tibco的daemon是什么 tibbon_客户端_02

Ribbon 负载均衡的策略

策略类

命名

描述

RandomRule

随机策略

随机选择 server

RoundRobinRule

轮询策略

按照顺序选择 server ( 默认策略)

RetryRule

重试策略

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

BestAvailableRule

最低并发策略

逐个考察 server,如果 server 断路器打开,则忽略,再选择其中并发链接最低的 server

AvailabilityFilteringRule

可用过滤策略

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

ResponseTimeWeightedRule

响应时间加权重策略

根据 server 的响应时间分配权重,响应时间越长,权重越低,被选择到的概率也就越低。响应时间越短,权重越高,被选中的概率越高,这个策略很贴切,综合了各种因素,比如:网络,磁盘,io 等,都直接影响响应时间

ZoneAvoidanceRule

区域权重策略

综合判断 server 所在区域的性能,和 server 的可用性,轮询选择 server 并且判断一个 AWS Zone 的运行性能是否可用,剔除不可用的 Zone 中的所有 server

Ribbon 的重试机制设置

ribbon 实现了负载均衡,如果访问某服务的 A 节点超时后,会触发 ribbon 的重试机制

全局设置
ribbon:
    ReadTimeout: 6000
    ConnectTimeout: 6000
    OkToRetryOnAllOperations: true
    MaxAutoRetries: 1
    MaxAutoRetriesNextServer: 2
    
局部服务设置
service-id:                             # 服务ID
    ribbon:
        ConnectTimeout: 6000            # 毫秒  连接超时时间
        ReadTimeout: 6000               # 毫秒  逻辑处理超时时间
        OkToRetryOnAllOperations: true  # 是否对所有操作都进行重试
        MaxAutoRetries: 1               # 对当前实例的最大重试次数(请求服务超时6s则会再请求一次)    
        MaxAutoRetriesNextServer: 1     # 切换实例的最大重试次数(如果还失败就切换下个实例访问,切换一次)

Ribbon工作流程

ribboneureka 配合使用的大致架构如下

tibco的daemon是什么 tibbon_服务器_03

服务发现

用于获取地址列表:当我们将 RibbonEureka 一起使用时,Ribbon 会到 Eureka 注册中心去获取服务端服务实例列表。它既可以是静态的(提供一组固定的地址),也可以是动态的(从注册中心中定期查询地址列表)

服务选择

服务选择规则:根据用户指定的策略,再从它的实例列表选择一个列表地址。其中 Ribbon 提供了很多策略,例如轮询,随机 ,根据响应时间加权等。得到一个具体的服务列表地址后,再通过Feign 完成服务的调用

服务监听

也就是随时剔除无效的服务实例