SpringCloud Netflix(四) : Ribbon负载均衡

简介

Ribbon是一个客户端IPC库,在云中进行了测试。它提供了以下特性

  • 负载均衡

  • 容错性

  • 异步反应模型中的多协议(HTTP、TCP、UDP)支持

  • 缓存和批量处理

 

基础使用

1.导入依赖

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

2.在RestTemplate Bean加上注解@LoadBalanced

@Bean
@LoadBalanced //默认采用的是RoundRobinRule,轮询策略
public RestTemplate restTemplate(){
    return new RestTemplate();
}

 

自定义负载均衡策略

源码分析

Riddon的负载均衡策略

通过查看Riddon的源码可以看出,Riddon的负载均衡策略类都继承了AbstractLoadBalancerRule

package com.netflix.loadbalancer;

import com.netflix.client.IClientConfigAware;

public abstract class AbstractLoadBalancerRule implements IRule, IClientConfigAware {
    private ILoadBalancer lb;

    public AbstractLoadBalancerRule() {
    }

    public void setLoadBalancer(ILoadBalancer lb) {
        this.lb = lb;
    }

    public ILoadBalancer getLoadBalancer() {
        return this.lb;
    }
}

AbstractLoadBalancerRule实现了Riddon的负载均衡方法接口 IRule

package com.netflix.loadbalancer;

public interface IRule {
    Server choose(Object var1);

    void setLoadBalancer(ILoadBalancer var1);

    ILoadBalancer getLoadBalancer();
}

所以我们只要继承AbstractLoadBalancerRule,重写IRule接口里的choose方法,并把自定义负载均衡策略的实现类通过配置类@Bean以IRule类型返回就可以自定义负载均衡策略了

自定义负载均衡策略实现

配置类不能放在@SpringBootApplication应用同级目类下,否则它由所有@RibbonClients共享,就达不到特殊化指定的目的了

CustomConfiguration类必须是@Configuration类,但请注意,对于主应用程序上下文,它不在@ComponentScan中。否则,它由所有@RibbonClients共享。如果您使用@ComponentScan(或@SpringBootApplication),则需要采取措施避免将其包括在内(例如,可以将其放在单独的,不重叠的程序包中,或指定要在@ComponentScan)。

  • 创建负载均衡策略的配置类
@Configuration
public class MyRuleConfig {
    @Bean
    public IRule ribbonRule(){
        return new MyRule();
    }
}
  • 创建负载均衡策略的实现类
public class MyRule extends AbstractLoadBalancerRule {

    private static Logger log = LoggerFactory.getLogger(MyRule.class);
    private int total = 0;
    private int index = 0;

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }
    @Override
    public Server choose(Object o) {
        return this.choose(this.getLoadBalancer(),o);
    }

    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        } else {
            Server server = null;

            while (server == null) {
                if (Thread.interrupted()) {
                    return null;
                }

                List<Server> upList = lb.getReachableServers();//获取可获得到的服务,即没有故障可以运行的服务
                List<Server> allList = lb.getAllServers();//获取所有服务
                int serverCount = allList.size();
                if (serverCount == 0) {
                    return null;
                }

                //自定义负载均衡方法,每个服务执行3次,依次轮询
                if (total<3){
                    server = (Server) upList.get(index);//根据索引从可获得的服务中获取服务
                    total++;
                }else {
                    total=0;
                    if (index>=upList.size()-1){
                        index=0;
                    }else {
                        index++;
                    }
                }

                if (server == null) {
                    Thread.yield();
                } else {
                    if (server.isAlive()) {
                        return server;
                    }

                    server = null;
                    Thread.yield();
                }
            }

            return server;
        }
    }
}
  • 在主配置类上添加@RibbonClient
@Configuration
//name为服务提供者配置的spring.application.name,configuration为自定义负载均衡的配置类
@RibbonClient(name = "SPRINGCLOUD-PROVIDER", configuration = MyRuleConfig.class) 
public class BeanConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

 

 

我的个人博客站

 
posted @ 2020-05-15 22:52  小高飞  阅读(616)  评论(0编辑  收藏  举报