一、Ribbon简介
Ribbon是Netflix发布的负载均衡器,它可以帮我们控制HTTP和TCP客户端的行为。只需为Ribbon配置服务提供者地址列表,Ribbon就可基于负载均衡算法计算出要请求的目标服务地址。
Ribbon默认为我们提供了很多的负载均衡算法,例如轮询、随机、响应时间加权等——当然,为Ribbon自定义负载均衡算法也非常容易,只需实现IRule
接口即可。
在Spring Cloud中,当Ribbon与Eureka配合使用时,Ribbon可自动从Eureka Server获取服务提供者地址列表,并基于负载均衡算法,选择其中一个服务提供者实例。下图展示了Ribbon与Eureka配合使用时的大致架构。
二、Ribbon入门
2.1 创建微服务
复制microservice-consumer-movie微服务,并改名为microservice-consumer-movie-ribbon,并修改pom.xml的配置文件修改artifactId标签的属性值为microservice-consumer-movie-ribbon,在application.yml文件中修改微服务名称为microservice-consumer-movie-ribbon,由于spring-cloud-starter-netflix-eureka-client
已经包含spring-cloud-starter-netfilx-ribbon
,故而无需额外添加依赖。
在启动类中,为restTemplate方法添加@LoadBalanced注解,微服务就修改完了。
package com.qhr.cloud.study;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @Author : qhr
* @Description :
* @Date : Created in 11:18 2020/7/8
* @Modified By :
*/
@SpringBootApplication
public class ConsumerMovieApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerMovieApplication.class, args);
}
}
调用
package com.qhr.cloud.study.controller;
import com.qhr.cloud.study.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @Author : qhr
* @Description :
* @Date : Created in 11:17 2020/7/8
* @Modified By :
*/
@RequestMapping("/movies")
@RestController
public class MovieController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/users/{id}")
public User findById(@PathVariable Long id) {
// 这里用到了RestTemplate的占位符能力
User user = this.restTemplate.getForObject(
"http://microservice-provider-user/users/{id}",
User.class,
id
);
// ...电影微服务的业务...
return user;
}
}
2.2 依次启动microservice-discovery-eureka、microservice-provider-user和microservice-consumer-movie-ribbon微服务,访问http://localhost:8761/
访问:http://localhost:8010/movies/users/1
可以看到现在可以通过服务名直接访问到对应的微服务,而不用通过微服务的ip跟端口。
三、Ribbon深入
3.1 内置负载均衡规则
负载均衡规则是Ribbon的核心,下面来看一下Ribbon内置的负载均衡规则。
- AvailabilityFilteringRule:过滤掉一直连接失败的被标记为circuit tripped的后端Server,并过滤掉那些高并发的后端Server或者使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个Server的运行状态;
- BestAvailableRule:选择一个最小的并发请求的Server,逐个考察Server,如果Server被tripped了,则跳过。
- RandomRule:随机选择一个Server;
- ResponseTimeWeightedRule:作用同WeightedResponseTimeRule,二者作用一样;
- RetryRule:对选定的负载均衡策略机上重试机制,在一个配置时间段内当选择Server不成功,则一直尝试使用subRule的方式选择一个可用的server;
- RoundRobinRule:轮询选择, 轮询index,选择index对应位置的Server;
- WeightedResponseTimeRule:根据响应时间加权,响应时间越长,权重越小,被选中的可能性越低;
- ZoneAvoidanceRule:复合判断Server所在区域的性能和Server的可用性选择Server;
如需自定义负载均衡规则,只需实现IRule
接口或继承AbstractLoadBalancerRule
、PredicateBasedRule即可
,读者可参考RandomRule
、RoundRobinRule
、ZoneAvoidanceRule
等内置Rule编写自己的负载均衡规则。
3.2 Ribbon配置自定义【细粒度配置】
3.2.1 代码配置方式
在Spring Cloud中,Ribbon的默认配置如下(格式是BeanType
beanName: ClassName
):
IClientConfig
ribbonClientConfig:DefaultClientConfigImpl
IRule
ribbonRule:ZoneAvoidanceRule
IPing
ribbonPing:NoOpPing
ServerList<Server>
ribbonServerList:ConfigurationBasedServerList
ServerListFilter<Server>
ribbonServerListFilter:ZonePreferenceServerListFilter
ILoadBalancer
ribbonLoadBalancer:ZoneAwareLoadBalancer
ServerListUpdater
ribbonServerListUpdater:PollingServerListUpdater
复制microservice-consumer-movie-ribbon微服务,并改名为microservice-consumer-movie-ribbon-config-java,新增Ribbon的配置文件
package config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author : qhr
* @Description :该类为Ribbon的配置类
* 注意:该类不能放在主应用程序上下文@ComponentScan所扫描的包中,否则配置将会被所有Ribbon Client共享。
* @Date : Created in 14:36 2020/7/10
* @Modified By :
*/
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule() {
// 负载均衡规则,改为随机
return new RandomRule();
}
}
创建一个空类,并在其上添加@Configuration
注解和@RibbonClient
注解.
package com.qhr.cloud.study.config;
import config.RibbonConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Configuration;
/**
* @Author : qhr
* @Description :使用RibbonClient,为特定的目标服务自定义配置。
* 使用@RibbonClient的configuration属性,指定Ribbon的配置类。
* 可参考的示例:
* http://spring.io/guides/gs/client-side-load-balancing/
* @Date : Created in 14:34 2020/7/10
* @Modified By :
*/
@Configuration
@RibbonClient(name = "microservice-consumer-movie-ribbon-config-java", configuration = RibbonConfiguration.class)
public class TestConfiguration {
}
由代码可知,使用@RibbonClient
注解的configuration属性,即可自定义指定名称Ribbon客户端的配置。
目录结构如下:
运行微服务
访问测试:
3.2.2 属性配置方式【推荐】
<clientName>.ribbon.
如下属性
NFLoadBalancerClassName
: should implementILoadBalancer
NFLoadBalancerRuleClassName
: should implementIRule
NFLoadBalancerPingClassName
: should implementIPing
NIWSServerListClassName
: should implementServerList
NIWSServerListFilterClassName
should implementServerListFilter
复制microservice-consumer-movie-ribbon微服务,并改名为microservice-consumer-movie-ribbon-config-properties,在application.yml中添加:
microservice-provider-user:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
运行测试:
访问测试: