初识Spring Cloud--Ribbon客户端负载均衡

Myth丶恋晨 2022-04-12 13:38 241阅读 0赞

首先来看一下Ribbon的作用:

ribbon 是一个客户端负载均衡器,主要是实现类似于 nginx的负载均衡的功能。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbGlzaGFkYWE_size_16_color_FFFFFF_t_70

SpringCloud提供了7种负载均衡的算法,如下表所示,ribbon 默认使用轮询算法(RoundRobinRule)来实现负载均衡,




















































策略名 策略声明 策略描述 实现说明
BestAvailableRule public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule     选择一个最小的并发请求的server 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server
AvailabilityFilteringRule public class AvailabilityFilteringRule extends PredicateBasedRule     过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值)     使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态
WeightedResponseTimeRule public class WeightedResponseTimeRule extends RoundRobinRule     根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。     一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetim
RetryRule public class RetryRule extends AbstractLoadBalancerRule     对选定的负载均衡策略机上重试机制。     在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server
RoundRobinRule public class RoundRobinRule extends AbstractLoadBalancerRule     roundRobin方式轮询选择server     轮询index,选择index对应位置的server
RandomRule public class RandomRule extends AbstractLoadBalancerRule     随机选择一个server     在index上随机,选择index对应位置的server
ZoneAvoidanceRule public class ZoneAvoidanceRule extends PredicateBasedRule     复合判断server所在区域的性能和server的可用性选择server     使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server)

下面我们通过代码来实现Ribbon的负载均衡功能;不同于dubbo的rpc调用,SpringCloud采用的rest方式进行服务调用,创建一个RemoteController类来模拟调用:

  1. @RestController
  2. @RequestMapping("/remote")
  3. public class RemoteController {
  4. private static final String URL_PREFIX = "http://SERVICE01";
  5. @Autowired
  6. private RestTemplate restTemplate;
  7. @GetMapping("/getService")
  8. public Object getRemoteService() {
  9. return restTemplate.getForObject(URL_PREFIX + "/local/getServiceInfo", Object.class);
  10. }
  11. }

其中的RestTemplate类需要手动的加载到IOC容器中,在启动类中添加如下的代码:

  1. @Bean
  2. @LoadBalanced
  3. public RestTemplate getRestTemplate() {
  4. return new RestTemplate();
  5. }

接着我们创建service01的多个实例:

20181203225130573.PNG

通过postman模拟请求,分别会调用这四个服务中的一个,并且调用的服务顺序是有序的。

那么如何调用其他的6种负载均衡算法呢?

timg_image_quality_80_size_b9999_10000_sec_1543859324246_di_fb20d6e54a86c6ca33f97fff11155bac_imgtype_0_src_http_3A_2F_2Fn.sinaimg.cn_2Fsinacn13_2F71_2Fw500h371_2F20180912_2F0b8f-fzrwica3327265.jpg

很简单,我们只要在启动类种添加如下的代码即可:

  1. @Bean
  2. public IRule getRule(){
  3. return new RandomRule();
  4. }

这时候可能又有一个疑问了,这个负载均衡的算法只能使用SpringCloud提供的7种算法吗?如果想要自己定义一个算法又该如何实现呢?

timg_image_quality_80_size_b9999_10000_sec_1543859324246_di_fb20d6e54a86c6ca33f97fff11155bac_imgtype_0_src_http_3A_2F_2Fn.sinaimg.cn_2Fsinacn13_2F71_2Fw500h371_2F20180912_2F0b8f-fzrwica3327265.jpg

假如这边有一个比较变态的需求,我只要service06给我提供服务那怎么操作呢?

依然简单,我们可以新建一个配置类:

  1. @Configuration
  2. public class CustomRule {
  3. @Bean
  4. public IRule getRule() {
  5. return new SingleRule();
  6. }
  7. }

自定义负载均衡算法:

  1. public class SingleRule extends AbstractLoadBalancerRule {
  2. public Server choose(ILoadBalancer lb, Object key) {
  3. if (lb == null) {
  4. return null;
  5. }
  6. Server server = null;
  7. while (server == null) {
  8. if (Thread.interrupted()) {
  9. return null;
  10. }
  11. List<Server> upList = lb.getReachableServers();
  12. List<Server> allList = lb.getAllServers();
  13. int serverCount = allList.size();
  14. if (serverCount == 0) {
  15. return null;
  16. }
  17. server = upList.get(0);
  18. if (server == null) {
  19. Thread.yield();
  20. continue;
  21. }
  22. if (server.isAlive()) {
  23. return (server);
  24. }
  25. // Shouldn't actually happen.. but must be transient or a bug.
  26. server = null;
  27. Thread.yield();
  28. }
  29. return server;
  30. }
  31. @Override
  32. public Server choose(Object o) {
  33. return choose(getLoadBalancer(), o);
  34. }
  35. @Override
  36. public void initWithNiwsConfig(IClientConfig iClientConfig) {
  37. }
  38. }

这里有一点需要注意:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbGlzaGFkYWE_size_16_color_FFFFFF_t_70 1

也就是说,这个配置类不能和之前的启动类放到启动类的同一个包下面,不然所有的ribbon客户端都会采用这个自定义的负载均衡算法。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbGlzaGFkYWE_size_16_color_FFFFFF_t_70 2

至此,一个自定义的负载均衡算法就实现啦,当然实际中估计没有人会这么用,具体的算法还是需要依据不同的业务来确定。

发表评论

表情:
评论列表 (有 0 条评论,241人围观)

还没有评论,来说两句吧...

相关阅读

    相关 负载均衡

    1 什么是负载均衡 当一台服务器的性能达到极限时,我们可以使用服务器集群来提高网站的整体性能。 那么,在服务器集群中,需要有一台服务器充当调度者的角色,用