八、SpringCloud之负载均衡器Ribbon

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29479041/article/details/83831533

一、简介

1、Ribbon

Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,RestTemplate、Feign、Zuul等都是使用了Ribbon。

2、Ribbon实现软负载均衡核心

  • 服务发现(发现依赖服务的列表,依据服务的名字,把该服务下所有的实例都找出来)
  • 服务选择规则(依据规则策略,如何从多个服务中选择一个有效的服务)
  • 服务监听(检测失效的服务,做到高效剔除)

3、Ribbon主要组件

通过ServerList获取所有可用服务列表,然后通过ServerListFilter过滤掉一部分地址,最后在剩下的地址中,通过IRule选择一个实例作为最终目标结果。

  • ServerList
  • IRule
  • ServerListFilter

二、追踪Ribbon源码


public class RibbonLoadBalancerClient implements LoadBalancerClient {

    public ServiceInstance choose(String serviceId) {
        return this.choose(serviceId, (Object)null);
    }

    public ServiceInstance choose(String serviceId, Object hint) {
        Server server = this.getServer(this.getLoadBalancer(serviceId), hint);
        return server == null ? null : new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
    }

    protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
        return loadBalancer == null ? null : loadBalancer.chooseServer(hint != null ? hint : "default");
    }
public class BaseLoadBalancer extends AbstractLoadBalancer implements PrimeConnectionListener, IClientConfigAware {
    //轮询规则
    private static final IRule DEFAULT_RULE = new RoundRobinRule();
    public Server chooseServer(Object key) {
        if (this.counter == null) {
            this.counter = this.createCounter();
        }

        this.counter.increment();
        if (this.rule == null) {
            return null;
        } else {
            try {
                return this.rule.choose(key);
            } catch (Exception var3) {
                logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", new Object[]{this.name, key, var3});
                return null;
            }
        }
    }
    
    //获取服务列表
    public List<Server> getAllServers() {
        //unmodifiableList不能修改的List
        return Collections.unmodifiableList(this.allServerList);
    }
public class ZoneAwareLoadBalancer<T extends Server> extends DynamicServerListLoadBalancer<T> {
 
    public ZoneAwareLoadBalancer(IClientConfig clientConfig, IRule rule, IPing ping, ServerList<T> serverList, ServerListFilter<T> filter, ServerListUpdater serverListUpdater) {
        super(clientConfig, rule, ping, serverList, filter, serverListUpdater);
    }
public class DynamicServerListLoadBalancer<T extends Server> extends BaseLoadBalancer {

    public DynamicServerListLoadBalancer(IClientConfig clientConfig, IRule rule, IPing ping, ServerList<T> serverList, ServerListFilter<T> filter, ServerListUpdater serverListUpdater) {
        super(clientConfig, rule, ping);
        this.isSecure = false;
        this.useTunnel = false;
        this.serverListUpdateInProgress = new AtomicBoolean(false);
        this.updateAction = new UpdateAction() {
            public void doUpdate() {
                DynamicServerListLoadBalancer.this.updateListOfServers();
            }
        };
        this.serverListImpl = serverList;
        this.filter = filter;
        this.serverListUpdater = serverListUpdater;
        if (filter instanceof AbstractServerListFilter) {
            ((AbstractServerListFilter)filter).setLoadBalancerStats(this.getLoadBalancerStats());
        }

        this.restOfInit(clientConfig);
    }
public class BaseLoadBalancer extends AbstractLoadBalancer implements PrimeConnectionListener, IClientConfigAware {
 
    public BaseLoadBalancer(IClientConfig config, IRule rule, IPing ping) {
        this.rule = DEFAULT_RULE;//轮询规则
        this.pingStrategy = DEFAULT_PING_STRATEGY;
        this.ping = null;
        this.allServerList = Collections.synchronizedList(new ArrayList());
        this.upServerList = Collections.synchronizedList(new ArrayList());
        this.allServerLock = new ReentrantReadWriteLock();
        this.upServerLock = new ReentrantReadWriteLock();
        this.name = "default";
        this.lbTimer = null;
        this.pingIntervalSeconds = 10;
        this.maxTotalPingTimeSeconds = 5;
        this.serverComparator = new ServerComparator();
        this.pingInProgress = new AtomicBoolean(false);
        this.counter = Monitors.newCounter("LoadBalancer_ChooseServer");
        this.enablePrimingConnections = false;
        this.changeListeners = new CopyOnWriteArrayList();
        this.serverStatusListeners = new CopyOnWriteArrayList();
        this.initWithConfig(config, rule, ping);
    }

三、自定义负载均衡策略

spring:
  application:
    name: order
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/SpringCloud_Sell?characterEncoding=utf-8&useSSL=false
  jpa:
    show-sql: true
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8866
#自定义负载均衡规则
PRODUCT:
  ribbon:
    #随机规则
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

猜你喜欢

转载自blog.csdn.net/qq_29479041/article/details/83831533