负载均衡策略AvailabilityFilteringRule

450 阅读1分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

20负载均衡策略AvailabilityFilteringRule

AvailabilityFilteringRule

/*
*
* Copyright 2013 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.netflix.loadbalancer;

import java.util.List;

import com.google.common.collect.Collections2;
import com.netflix.client.config.IClientConfig;
import com.netflix.servo.annotations.DataSourceType;
import com.netflix.servo.annotations.Monitor;

/**
 * A load balancer rule that filters out servers that:
 * <ul>
 * <li> are in circuit breaker tripped state due to consecutive connection or read failures, or</li>
 * <li> have active connections that exceeds a configurable limit (default is Integer.MAX_VALUE).</li>
 * </ul>
 * The property
 * to change this limit is 
 * <pre>{@code
 * 
 * <clientName>.<nameSpace>.ActiveConnectionsLimit
 * 
 * }</pre>
 *
 * <p>
 *   
 * @author awang
 *
 */
public class AvailabilityFilteringRule extends PredicateBasedRule {    

    private AbstractServerPredicate predicate;
    
    public AvailabilityFilteringRule() {
       super();
       predicate = CompositePredicate.withPredicate(new AvailabilityPredicate(this, null))
                .addFallbackPredicate(AbstractServerPredicate.alwaysTrue())
                .build();
    }
    
    
    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {
       predicate = CompositePredicate.withPredicate(new AvailabilityPredicate(this, clientConfig))
                   .addFallbackPredicate(AbstractServerPredicate.alwaysTrue())
                   .build();
    }

    @Monitor(name="AvailableServersCount", type = DataSourceType.GAUGE)
    public int getAvailableServersCount() {
       ILoadBalancer lb = getLoadBalancer();
       List<Server> servers = lb.getAllServers();
       if (servers == null) {
          return 0;
       }
       return Collections2.filter(servers, predicate.getServerOnlyPredicate()).size();
    }


    /**
     * This method is overridden to provide a more efficient implementation which does not iterate through
     * all servers. This is under the assumption that in most cases, there are more available instances 
     * than not. 
     */
    @Override
    public Server choose(Object key) {
        int count = 0;
        Server server = roundRobinRule.choose(key);
        while (count++ <= 10) {
            if (predicate.apply(new PredicateKey(server))) {
                return server;
            }
            server = roundRobinRule.choose(key);
        }
        return super.choose(key);
    }

    @Override
    public AbstractServerPredicate getPredicate() {
        return predicate;
    }
}

AvailabilityFilteringRule继承了PredicateBasedRule,采用先过滤清单后轮询选择的基本处理逻辑,过滤条件使用了AvailabilityPredicate的apply方法:

@Override
public boolean apply(@Nullable PredicateKey input) {
    LoadBalancerStats stats = getLBStats();
    if (stats == null) {
        return true;
    }
    return !shouldSkipServer(stats.getSingleServerStat(input.getServer()));
}

AvailabilityFilteringRule重写了choose方法,没有像PredicateBasedRule中的先遍历所有的节点进行过滤,然后从过滤后的集合中选择实例,而是先线性选择一个实例,然后用过滤条件判断是否满足条件,如此循环,重复10次没有找到再采用父类的实现方案。