技术标签: 【面试精选】 微服务 面试 负载均衡 spring cloud 【架构】 ribbon 【微服务】
Ribbon是Netflix开源的客户端负载均衡器,它可以很好的控制HTTP和TCP客户端的行为。Ribbon支持配置客户端添加重试和超时等功能,旨在使客户端更加强健。Ribbon在分布式系统中提供一系列完整的服务,如:
目前Ribbon支持负载均衡的策略有:
Ribbon实现负载均衡的核心思想是客户端通过轮询(RoundRobin)等负载均衡策略从服务注册中心获取服务实例列表,然后缓存到本地,客户端根据负载均衡策略选择一个服务实例发送请求。
Ribbon的处理流程:
Ribbon通过以上流程实现了负载均衡和容错。
引入依赖
在Spring Cloud项目中引入:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
开启Ribbon
在应用主类上添加@RibbonClient
注解开启Ribbon,并指定服务名。例如:
@SpringBootApplication
@RibbonClient(name = "service-name")
public class RibbonApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonApplication.class, args);
}
}
使用RestTemplate访问服务
通过RestTemplate
的loadBalanced
方法开启Ribbon的负载均衡功能。例如:
@Autowired
private RestTemplate restTemplate;
@Bean
public RestTemplate getRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setLoadBalancer(myLoadBalancer()); // 开启负载均衡
return restTemplate;
}
public String doOtherStuff() {
String result = restTemplate.getForObject("http://service-name/doStuff", String.class);
}
当doOtherStuff()
方法请求http://service-name/doStuff
时,Ribbon会根据配置的负载均衡策略,选择一个service-name
服务实例发送请求。
Ribbon目前支持以下几种负载均衡算法:
配置负载均衡算法
要配置Ribbon的负载均衡算法,需要在@RibbonClient
指定的服务名称下添加配置。例如:
service-name:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
上面例子将为service-name
服务设置RandomRule
随机负载均衡算法。
如果要实现自定义的负载均衡算法,可以实现IRule
接口,然后将实现类全类名配置为NFLoadBalancerRuleClassName
的值。
配置服务实例的可访问性检查
Ribbon中使用IClientConfig
接口来定义服务实例的一些配置,我们可以实现该接口的getClientConfigKey
方法指定服务实例的可访问性检查,例如:
public class MyClientConfig implements IClientConfig {
@Override
public String getClientConfigKey() {
return "MyClientConfig";
}
}
然后在yml中配置:
service-name:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.MyClientConfig
这将为service-name
服务启用MyClientConfig
的配置,进而实现自定义的服务实例可访问性检查逻辑。
连接池和超时
Ribbon提供了对连接池和超时时间的配置,我们可以在yml文件中配置:
service-name:
ribbon:
MaxAutoRetries: 1 # 最大自动重试次数
MaxAutoRetriesNextServer: 1 # 切换服务器最大重试次数
OkToRetryOnAllOperations: true # 是否所有操作都重试
ConnectTimeout: 3000 # 连接超时时间(ms)
ReadTimeout: 3000 # 读取超时时间(ms)
ConnPoolTTL: 60000 # 连接池中连接存活时间(ms)
以上配置可以很好的提高Ribbon的容错性和服务可靠性。
重试机制
如前面所述,Ribbon的RetryRule
和MaxAutoRetries
配置实现了重试机制。当我们请求的服务实例在指定时间内没有响应时,Ribbon会自动重试其他服务实例,这可以避免因为某个实例故障导致服务不可用的情况。
熔断机制
Ribbon默认也实现了基本的熔断机制。当一个服务实例长时间不可达时,Ribbon会将其从服务实例清单中剔除一段时间,这个时间由NIWSServerListPoller
的serverListRefreshInterval
属性配置,默认是30秒。
此外,Ribbon还可以与Netflix Hystrix结合使用,实现更为强大的熔断和容错功能。在熔断打开期间,Ribbon将不会向熔断的实例发送请求。
获取服务实例清单的时间控制
Ribbon通过NIWSServerListPoller
控制去服务注册中心获取服务实例清单的时间间隔,该时间间隔由serverListRefreshInterval
属性配置,默认为30秒。
请求重试
在请求失败时,Ribbon可以自动发起重试请求。重试次数由MaxAutoRetries
和MaxAutoRetriesNextServer
控制,这两个属性默认都是1次。当MaxAutoRetries
重试次数用完,Ribbon会切换到另一个服务实例发起MaxAutoRetriesNextServer
重试次数的请求。
手动刷新服务实例清单
除了定时去获取服务实例清单外,我们也可以手动刷新。例如:
@Autowired
private ServerListUpdater serverListUpdater;
public void refreshServers() {
serverListUpdater.refresh(true);
}
调用refresh(true)
方法可以立即强制刷新服务实例清单。
以上就是Ribbon的一些高级特性,可以让我们更好的利用Ribbon实现服务调用的高可用。
了解Ribbon的原理和使用后,我们来分析一下其源码,以便获得更深入的理解。
ServerList
ServerList
接口定义获取服务实例清单的接口,其实现类ConfigurationBasedServerList
从服务注册中心获取服务实例清单。ServerList
的具体实现类由ServerListImpl<T>
类的NIWSServerListClassName
属性配置。
ILoadBalancer
ILoadBalancer
接口定义负载均衡算法接口,其实现类RoundRobinRule
、RandomRule
等实现相应的负载均衡算法。ILoadBalancer
的具体实现由BaseLoadBalancer
的rule
属性配置。
IPing
IPing
接口定义服务实例健康检查接口,其实现类DummyPing
返回所有服务实例都是健康的。IPing
的具体实现由BaseLoadBalancer
的ping
属性配置。
ServerListUpdater
ServerListUpdater
定时从ServerList
的实现类ConfigurationBasedServerList
获取最新的服务实例清单,并通知LoadBalancerClient
刷新本地缓存的服务实例清单。获取服务实例清单的时间间隔由pollingInterval
属性配置。
LoadBalancerClient
LoadBalancerClient
维护一个服务实例清单的本地缓存,其使用ServerListUpdater
定时获取最新的服务实例清单更新本地缓存。LoadBalancerClient
也维护一个用于选择服务实例的BaseLoadBalancer
。
LoadBalancerClient
维护一个服务实例清单的本地缓存,其使用ServerListUpdater
定时获取最新的服务实例清单更新本地缓存。LoadBalancerClient
也维护一个用于选择服务实例的BaseLoadBalancer
。
过上面的源码类介绍可以清楚的了解Ribbon的内部工作机制:
ServerListUpdater
定时从ConfigurationBasedServerList
获取服务实例清单LoadBalancerClient
维护服务实例清单本地缓存和BaseLoadBalancer
LoadBalancerClient
使用BaseLoadBalancer
选择一个服务实例BaseLoadBalancer
的负载均衡算法由ILoadBalancer
实现,健康检查由IPing
实现NIWSServerListClassName
、NFLoadBalancerRuleClassName
和NFLoadBalancerPingClassName
指定ServerList
、ILoadBalancer
和IPing
的实现类尽管Ribbon是一个比较成熟和流行的负载均衡器,但它也存在一定的局限性:
除Ribbon外,目前还有其他几种负载均衡器可以选择:
综上,如果你的系统已经使用了Spring Cloud,那么首选Spring Cloud Loadbalancer。如果需要更高性能和更强大的功能,可以选择HAProxy或Envoy。如果你的系统比较简单,Nginx也是一个不错的选择。Ribbon由于其局限性,现在已经逐渐被其他负载均衡器取代。
我们了解到Ribbon的大部分配置都是通过ribbon.<clientName>.*
的方式在application.yml
文件中完成的。除此之外,Ribbon还有一些高级配置需要编程实现。
自定义负载均衡规则
我们可以实现IRule
接口自定义负载均衡规则,例如:
public class CustomRule implements IRule {
@Override
public Server choose(Object key) {
// 实现自定义选择逻辑
// ...
}
}
然后在application.yml
中配置:
ribbon:
CustomConfiguration:
NFLoadBalancerRuleClassName: com.example.CustomRule
这将为CustomConfiguration
客户端启用我们自定义的CustomRule
负载均衡规则。
自定义服务实例选择逻辑
除了负载均衡规则外,我们还可以自定义服务实例选择逻辑。例如:
public class CustomLoadBalancer extends BaseLoadBalancer {
@Override
public Server chooseServer(Object key) {
// 实现自定义选择逻辑
// ...
}
}
然后在RestTemplate
中配置:
RestTemplate restTemplate = new RestTemplate();
restTemplate.setLoadBalancer(new CustomLoadBalancer());
这将为通过该RestTemplate
发起的请求使用自定义的负载均衡选择逻辑。
自定义服务实例健康检查
我们可以实现IPing
接口自定义服务实例健康检查逻辑,例如:
public class CustomPing implements IPing {
@Override
public boolean isAlive(Server server) {
// 实现自定义健康检查逻辑
// ...
}
}
然后在application.yml
中配置:
ribbon:
CustomConfiguration:
NFLoadBalancerPingClassName: com.example.CustomPing
这将为CustomConfiguration
客户端启用我们自定义的CustomPing
健康检查逻辑。
关闭服务实例健康检查
如果我们不希望Ribbon对服务实例进行健康检查,可以将NFLoadBalancerPingClassName
配置为com.netflix.loadbalancer.NoOpPing
。例如:
ribbon:
CustomConfiguration:
NFLoadBalancerPingClassName: com.netflix.loadbalancer.NoOpPing
这将完全关闭针对CustomConfiguration
客户端的服务实例健康检查。
以上就是Ribbon的一些高级配置,我们可以较为灵活的定制Ribbon以满足我们的需求。希望本文能提供一些编程实现Ribbon高级配置的思路和示例。
Ribbon本身对服务实例熔断支持较弱,但是它可以很好的与Netflix Hystrix结合使用,以实现更加强大的熔断功能。
Hystrix简介
Hystrix是一个针对分布式系统的延迟和容错的开源库,它通过添加延迟容错和断路器等功能帮助分布式系统提高其弹性。Hystrix主要提供了以下功能:
使用步骤
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
在主应用上添加@EnableCircuitBreaker
注解开启Hystrix。
使用@HystrixCommand
注解为服务方法添加熔断功能,例如:
@HystrixCommand(fallbackMethod = "fallbackMethod")
public String serviceMethod() {
// ...
}
public String fallbackMethod() {
return "Fallback response";
}
这将为serviceMethod()
方法添加熔断功能,当该方法触发熔断时会调用fallbackMethod()
方法返回备选响应。
我们可以在application.yml
中配置Hystrix的各项参数,详见Hystrix Wiki。
Hystrix提供了监控指标而可以实时监控熔断状态,这需要结合Hystrix Dashboard使用。
Ribbon与Hystrix的集成
Spring Cloud已经帮助我们将Ribbon和Hystrix进行了很好的集成:
@LoadBalanced
注解的RestTemplate
访问某服务失败时,如果该服务已添加Hystrix熔断注解,将自动触发熔断。@HystrixCommand
注解,就可以为Ribbon的服务调用添加熔断功能,无需其他集成配置。所以,如果需要为Ribbon添加强大的熔断功能,Hystrix是一个很好的选择。它可以和Ribbon完美整合,为服务调用添加熔断、降级、限流等功能。
在系列文章的最后,我想与大家分享一些使用Ribbon的最佳实践。
合理配置超时时间
Ribbon中的超时配置包括:
ConnectTimeout
:连接超时时间,建立TCP连接的超时时间。ReadTimeout
:读取超时时间,接收服务端响应的超时时间。这两个超时时间直接关系到Ribbon的容错性能,我们需要根据服务的响应时间来合理设置:
ConnectTimeout
应略大于服务的ping时间,以防止pong消息丢失被误判为连接失败。ReadTimeout
应稍大于服务的正常响应时间,但不应太长,以快速检测到服务异常。过长的超时时间会导致故障检测变慢,但过短的超时时间会产生误判。所以需要根据实际服务情况合理设置。
开启重试机制
Ribbon的重试机制可以避免短暂的服务故障导致的请求失败,我们应该根据具体业务开启Ribbon的重试功能:
ribbon:
MaxAutoRetries: 1 # 最大重试次数
MaxAutoRetriesNextServer: 1 # 重试下一个服务实例的最大次数
但是重试次数不应设置太高,以免漏掉真正的服务故障。
合理控制刷新服务实例清单的频率
Ribbon定时去服务注册中心刷新服务实例清单,这由NIWSServerListRefreshInterval
属性控制,默认30秒。
如果刷新过于频繁,会加大注册中心的压力;但如果刷新不够频繁,Ribbon无法快速感知服务实例的变化。
所以,需要根据服务实例的变化频率来设置这个时间间隔。如果服务实例很稳定,可以设置长一点的时间间隔;如果服务实例经常Changed,这个时间间隔应适当缩短。
一般来说,30秒是一个比较适中的时间间隔。当服务实例发生变化时,也可以调用ServerListUpdater.refresh()
方法手动刷新服务实例清单。
开启和监控Hystrix
如果Ribbon与Hystrix结合使用,我们应该:
@EnableCircuitBreaker
@HystrixCommand
这可以让Ribbon实现更加智能和弹性的服务调用。
以上就是一些在实际项目中使用Ribbon的最佳实践,可以让Ribbon工作的更加稳定和高效。在你的项目中,可以根据实际情况选择适用的最佳实践。
OK,本系列文章围绕Ribbon这个流行的负载均衡器进行了全面而深入的学习。主要内容包括:
通过本文的学习,相信你对Ribbon和服务调用都有比较深入的理解。Ribbon作为一个轻量级的负载均衡器,适用于绝大多数的服务体系架构。我希望本教程能真正帮助你掌握Ribbon并在项目中灵活运用。
文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99
文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效
文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是
文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件
文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件
文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码
文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware
文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停
文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待
文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析
文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code
文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象