1Ribbon是什么
Ribbon是一个开源的客户端负载均衡器由Netflix发布是SpringCloud-Netflix中重要的一环通过它将Netflix的中间层服务连接在一起。
Ribbon客户端组件提供一系列完善的配置项如连接超时、重试等。简单的说就是在配置文件中列出Load Balancer后面所有的服务Ribbon会自动的基于某种规则如简单轮询随机连接等去连接这些服务也很容易实现自定义的负载均衡算法。
2Ribbon能干什么
Ribbon是在客户端来实现负载均衡的访问服务主要的功能点
- 服务发现发现依赖服务的列表
- 服务选择规则在多个服务中如何选择一个有效服务
- 服务监听检测失效的服务高效剔除失效服务
3代码实例
加入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
官方的HelloWorld具体示例参看
https://github.com/Netflix/ribbon/wiki/Getting-Started
4参数配置
4.1概述
对于Ribbon参数的key以及value类型的定义可以通过com.netflix.client.config.CommonClientConfigKey查看
如果你没有配置任何属性则ribbon会使用com.netflix.client.config.DefaultClientConfigImpl里的值
4.2配置方式
Ribbon的参数配置通常有二种方式全局配置以及指定客户端配置
- 全局配置的方式很简单只需要使用ribbon.=格式进行配置即可。
其中代表了Ribbon客户端配置的参数名则代表了对应参数的值。
比如可以向下面这样配置Ribbon的超时时间
ibbon.ConnectTimeout=250
全局配置可以作为默认值进行设置当指定客户端配置了相应的key的值时将覆盖全局配置的内容 - 指定客户端的配置方式
.ribbon.=的格式进行配置
表示服务名比如没有服务治理框架的时候如Eureka需要指定实例清单如userService.ribbon.listOfServers=localhost:8080
##4.3配置示例my.properties
# Max number of retries on the same server (excluding the first try)
hello-client.ribbon.MaxAutoRetries=1
# Max number of next servers to retry (excluding the first server)
hello-client.ribbon.MaxAutoRetriesNextServer=1
# Whether all operations can be retried for this client
hello-client.ribbon.OkToRetryOnAllOperations=true
# Interval to refresh the server list from the source
hello-client.ribbon.ServerListRefreshInterval=2000
# Connect timeout used by Apache HttpClient
hello-client.ribbon.ConnectTimeout=3000
# Readtimeout used by Apache HttpClient
hello-client.ribbon.ReadTimeout=3000
# Initial list of servers, can be changed via Archaius dynamic property at runtime
#ribbon.listOfServers=localhost:8765
hello-client.ribbon.listOfServers=localhost:8765,localhost:8766
hello-client.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
ConfigurationManager.loadPropertiesFromResources("my.properties"); // 1
System.out.println(
ConfigurationManager.getConfigInstance()
.getProperty("hello-client.ribbon.listOfServers"));
RestClient client = (RestClient) ClientFactory.getNamedClient("hello-client"); // 2
HttpRequest request = HttpRequest.newBuilder().uri(new URI("/userServiceProvider?name=cc5")).build(); // 3
for (int i = 0; i < 15; i++) {
HttpResponse response = client.executeWithLoadBalancer(request); // 4
System.out.println("Status code for " + response.getRequestedURI() + " :" + response.getStatus());
}
4.4启动查看日志:
5Ribbon核心组件
5.1Ribbon核心组件
- IRule根据特定算法中从服务列表中选取一个要访问的服务
- IPing后台运行线程用来判断服务是否可用
- ServerList 服务列表可以是静态的或动态的。如果它是动态的后台线程将刷新并按一定的时间间隔过滤列表
- ServerListFilter该接口允许过滤配置或动态获取的具有所需特性的服务器列表
- ServerListUpdater被DynamicServerListLoadBalancer用于动态的更新服务列表
- IClientConfig定义各种配置信息用来初始化ribbon客户端和负载均衡器
- ILoadBalancer定义软件负载平衡器操作的接口。动态更新一组服务列表及根据指定算法从现有服务器列表中选择一个服务
5.2配置
这些组件可以以编程方式设置也可以是客户端配置属性的一部分并通过反射创建。
支持的属性如下所示应以.ribbon.为前缀
- NFLoadBalancerClassName要使用的ILoadBalancer
- NFLoadBalancerRuleClassName要使用的Irule
- NFLoadBalancerPingClassName要使用的Iping
- NIWSServerListClassName要使用的ServerList
- NIWSServerListFilterClassName要使用的ServerListFilter
5.3IRule常用实现有以下几种
都在com.netflix.loadbalancer包下面
1RoundRobinRule轮询规则
2RandomRule随机获取一个服务
3AvailabilityFilteringRule 这个负载均衡器规则会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务还有并发的连接数量超过阈值的服务然后对剩余的服务列表按照轮询策略进行访问
4WeightedResponseTimeRule 根据平均响应时间计算所有服务的权重响应时间越快服务权重越大、被选中的概率越高。刚启动时如果统计信息不足则使用RoundRobinRule策略等统计信息足够会切换到WeightedResponseTimeRule。
5RetryRule 先按照RoundRobinRule的策略获取服务如果获取服务失败则在指定时间内会进行重试获取可用的服务
6BestAvailableRule 此负载均衡器会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务然后选择一个并发量最小的服务
7ZoneAvoidanceRule默认规则,复合判断server所在区域的性能和server的可用性选择server
5.4IPing常用实现有以下几种
都在com.netflix.loadbalancer包下面
1DummyPing默认实现默认返回true即认为服务永远活着
2NIWSDiscoveryPing 不执行真正的ping。如果Discovery Client认为是在线则程序认为本次心跳成功服务活着
3PingUrl 此组件会使用HttpClient调用服务的一个URL如果调用成功则认为本次心跳成功表示此服务活着。
4NoOpPing永远返回true即认为服务永远活着
ServerList常用实现有以下几种
都在com.netflix.loadbalancer包下面
1ConfigurationBasedServerList从配置文件中获取所有服务列表也是静态获取服务列表配置例子sample-client.ribbon.listOfServers=
2DiscoveryEnabledNIWSServerList 从Eureka Client中获取服务列表。此值必须通过属性中的VipAddress来标识服务器集群。DynamicServerListLoadBalancer会调用此对象动态获取服务列表
3DomainExtractingServerList代理类根据ServerList的值实现具体的逻辑
5.5ServerListFilter常用实现有以下几种
都在com.netflix.loadbalancer包下面
1ZoneAffinityServerListFilter 过滤掉所有的不和客户端在相同zone的服务如果和客户端相同的zone不存在才不过滤不同zone有服务。启用此配置使用以下配置.ribbon.EnableZoneAffinity=true
2ServerListSubsetFilter ZoneAffinityServerListFilter的子类。此过滤器确保客户端仅看到由ServerList实现返回的整个服务器的固定子集。 它还可以定期用新服务器替代可用性差的子集中的服务器。要启用此过滤器请指定以下属性
myClient.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
// the server must register itself with Eureka server with VipAddress "myservice"
myClient.ribbon.DeploymentContextBasedVipAddresses=myservice
myClient.ribbon.NIWSServerListFilterClassName=com.netflix.loadbalancer.ServerListSubsetFilter
only show client 5 servers. default is 20.
myClient.ribbon.ServerListSubsetFilter.size=5
5.6ServerListUpdater常用实现有以下几种
都在com.netflix.loadbalancer包下面
1PollingServerListUpdater 默认的实现策略。此对象会启动一个定时线程池定时执行更新策略
2EurekaNotificationServerListUpdater 当收到缓存刷新的通知会更新服务列表。
IClientConfig常用实现有以下几种
1com.netflix.client.config.DefaultClientConfigImplIClientConfig的默认实现
5.7ILoadBalancer常用实现有以下几种
都在com.netflix.loadbalancer包下面
1DynamicServerListLoadBalancer DynamicServerListLoadBalancer组合Rule、IPing、ServerList、ServerListFilter、ServerListUpdater 实现类实现动态更新和过滤更新服务列表
2ZoneAwareLoadBalancer 这是DynamicServerListLoadBalancer的子类主要加入zone的因素。统计每个zone的平均请求的情况保证从所有zone选取对当前客户端服务最好的服务组列表
6结合Eureka
6.1代码示例准备多个服务注册到eureka
1先加入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
可以不用加入Ribbon依赖因为Eureka的starter里面包含了ribbon
2写一个配置类提供RestTemplate示例如下
@Bean
@LoadBalanced
public RestTemplate rt(){
return new RestTemplate();
}
3写一个Hello2的Controller在方法里面使用RestTemplate
@RestController
public class Hello2 {
@Autowired
private RestTemplate rt;
@Autowired
private LoadBalancerClient lbc;
@RequestMapping("/ribbon2")
public String ribbon2() {
String s = rt.getForObject("http://userService/userServiceProvider?name=cc5", String.class);
System.out.println("s==="+s);
return "okok";
}
}
4启动SpringBoot的启动类然后就可以通过页面进行访问测试了
多次点击
6.2说明
1RestTemplate 是Spring提供的用于访问Rest服务的客户端RestTemplate提供了多种便捷访问远程Http服务的方法能够大大提高客户端的编写效率。
2@LoadBalanced表示restTemplate使用LoadBalancerClient执行请求会自动使用负载均衡策略它内部会在RestTemplate中加入LoadBalancerInterceptor这个拦截器这个拦截器的作用就是使用负载均衡。这样在访问远程服务的时候可以直接使用Provider向Eureka Server注册的虚拟名字如
rt.getForObject(“http://userService/userServiceProvider?name=cc”, String.class);
3当Eureka与Ribbon结合使用即两者都在类路径上时ribbonServerList将被扩展为DiscoveryEnabledNIWSServerList扩展名为Eureka的服务器列表。它还用NIWSDiscoveryPing替换IPing接口代理到Eureka以确定服务器是否启动。
4可以通过代码来进行配置比如配置IRule、IPing等
5设置属性ribbon.eureka.enabled = false将明确禁用在Ribbon中使用Eureka
7重试机制
SpringCloud通过整合Spring retry来增强RestTemplate的重试能力对于开发者来说只需要简单配置即可完成重试策略配置示例如下
//该参数用来开启重试机制它默认是关闭的
spring.cloud.loadbalancer.retry.enabled=true
//断路器的超时时间需要大于Ribbon的超时时间不然不会触发重试
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
//请求连接超时时间
userService.ribbon.ConnectTimeout=250
//请求处理的超时时间
userService.ribbon.ReadTimeout=1000
//对所有操作请求都进行重试
userService.ribbon.OkToRetryOnAllOperations=true
//切换实例的重试次数
userService.ribbon.MaxAutoRetriesNextServer=2
//对当前实例的重试次数
userService.ribbon.maxAutoRetries=1
8: @RibbonClient
注解@RibbonClient这样做的目的是为了在启动该微服务的时候就能去加载我们的自定义Ribbon配置类从而使配置生效形如
@RibbonClient(name=“userService”,configuration=MyConf2.class)
1这个userService不是随便写的而是注册到Eureka发现组件上的微服务服务端意思是要对所有工程名为userService的服务提供者进行负载均衡管理
2官方文档明确给出了警告这个测试配置类MyConf2不能放在@ComponentScan所扫描的当前包下以及子包下否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享也就是说我们达不到特殊化定制的目的了。