基于dubbo和zookeeper,拓展内部负载器,结合一致哈希和最少活跃优先

文章介绍了如何在Dubbo中扩展内置的一致性哈希和最少活跃优先策略,创建了一个自定义负载均衡器`CustomLoadBalance`。通过这个策略,当选择的节点不可用或负载过高时,会顺延选择下一组节点。实现包括利用`ConsistentHashLoadBalance`和`LeastActiveLoadBalance`,以及`isInvokerAvailable`和`isInvokerOverloaded`方法来判断节点的可用性和负载情况。

这版主要是拓展dubbo中的一致哈希和最少活跃优先

方案:基于 Dubbo 和 Zookeeper 的内置一致性哈希法和最少活跃法进行扩展,实现一个结合这两种策略的自定义负载均衡策略。当选择的节点不可用或负载过高时,顺延选择下一组集合。

  1. 首先,创建一个自定义负载均衡策略类,继承自 AbstractLoadBalance
    import org.apache.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance;
    import org.apache.dubbo.common.URL;
    import org.apache.dubbo.rpc.Invocation;
    import org.apache.dubbo.rpc.Invoker;
    
    import java.util.List;
    
    public class CustomLoadBalance extends AbstractLoadBalance {
        @Override
        protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
            // 使用一致性哈希算法找到离请求哈希值最近的三个虚拟节点
            List<Invoker<T>> nearestInvokers = findNearestInvokers(invokers, url, invocation);
    
            // 从这些虚拟节点对应的实际节点中使用最少活跃法选择一个节点
            return findLeastActiveInvoker(nearestInvokers, url, invocation);
        }
    
        // 在这里实现 findNearestInvokers 和 findLeastActiveInvoker 方法
    
    
      }
    

  2. 修改 CustomLoadBalance 类中的 findNearestInvokersfindLeastActiveInvoker 方法,以分别调用 Dubbo 内置的一致性哈希负载均衡策略和最少活跃优先负载均衡策略。同时实现 isInvokerAvailableisInvokerOverloaded 方法,以判断 Invoker 是否可用以及负载是否过高:
    import org.apache.dubbo.rpc.cluster.loadbalance.ConsistentHashLoadBalance;
    import org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance;
    
    import java.util.ArrayList;
    
    private ConsistentHashLoadBalance consistentHashLoadBalance = new ConsistentHashLoadBalance();
    private LeastActiveLoadBalance leastActiveLoadBalance = new LeastActiveLoadBalance();
    
    private <T> List<Invoker<T>> findNearestInvokers(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        // ... 使用 Dubbo 内置的一致性哈希负载均衡策略找到离请求哈希值最近的三个虚拟节点
            List<Invoker<T>> nearestInvokers = new ArrayList<>(3);
            for (int i = 0; i < 3; i++) {
                Invoker<T> invoker = consistentHashLoadBalance.select(invokers, url, invocation);
                nearestInvokers.add(invoker);
                invokers.remove(invoker);
            }
            return nearestInvokers;
    }
    
    
    private <T> Invoker<T> findLeastActiveInvoker(List<Invoker<T>> nearestInvokers, URL url, Invocation invocation) {
        // ... 使用 Dubbo 内置的最少活跃优先负载均衡策略从离请求哈希值最近的三个虚拟节点中选择一个节点
    Invoker<T> selectedInvoker = leastActiveLoadBalance.select(nearestInvokers, url, invocation);
            int retryCount = 0;
            int maxRetry = 3;
    
            while (retryCount < maxRetry) {
                if (isInvokerAvailable(selectedInvoker) && !isInvokerOverloaded(selectedInvoker)) {
                    return selectedInvoker;
                } else {
                    nearestInvokers.remove(selectedInvoker);
                    if (!nearestInvokers.isEmpty()) {
                        selectedInvoker = leastActiveLoadBalance.select(nearestInvokers, url, invocation);
                    } else {
                        nearestInvokers = findNextNearestInvokers(invokers, url, invocation);
                        selectedInvoker = leastActiveLoadBalance.select(nearestInvokers, url, invocation);
                    }
                }
                retryCount++;
            }
            return selectedInvoker;
    
    }
    
    private <T> boolean isInvokerAvailable(Invoker<T> invoker) {
    
      // 例如判断 Invoker 是否可用
        if (invoker.isAvailable()) {
            return true;
        } else {
            // 可以添加其他判断逻辑,例如检查 Invoker 的状态、网络连接等
            return false;
        }
    }
    
    private <T> boolean isInvokerOverloaded(Invoker<T> invoker) {
        // 判断 Invoker 是否负载过高
    // 可以根据实际情况实现具体判断逻辑,例如检查 Invoker 的负载、资源占用等
    // ...
    // 例如获取 Invoker 当前的活跃连接数
        RpcStatus rpcStatus = RpcStatus.getStatus(invoker.getUrl());
        int activeCount = rpcStatus.getActive();
    
        // 计算集合内所有 Invoker 的活跃连接数平均值
        double averageActiveCount = invokers.stream()
            .mapToInt(invokerInList -> RpcStatus.getStatus(invokerInList.getUrl()).getActive())
            .average()
            .orElse(0);
    
        // 判断 Invoker 是否负载过高
        if (activeCount > averageActiveCount * overloadThreshold) {
            return true;
        } else {
            return false;
        }
    }
    
    private <T> List<Invoker<T>> findNextNearestInvokers(List<Invoker<T>> invokers, URL url, Invocation invocation) {
    // ... 重新计算离原始节点最远的虚拟节点集合
    List<Invoker<T>> nextNearestInvokers = new ArrayList<>(3);
    for (int i = 0; i < 3; i++) {
        Invoker<T> invoker = consistentHashLoadBalance.select(invokers, url, invocation);
        nextNearestInvokers.add(invoker);
        invokers.remove(invoker);
    }
    return nextNearestInvokers;
    
    }
    

    isInvokerAvailablesInvokerOverloaded这两个方法中,我们使用了 Dubbo 提供的 RpcStatus 类来获取 Invoker 的活跃连接数。在 isInvokerAvailable 方法中,我们通过检查 Invoker 的可用状态来判断其是否可用。在 isInvokerOverloaded 方法中,我们比较 Invoker 的活跃连接数与集合内所有 Invoker 的活跃连接数平均值的乘积,以判断其是否负载过高。overloadThreshold 参数用于设置负载过高的阈值,例如设置为 1.5 表示当 Invoker 的活跃连接数高于集合内所有 Invoker 活跃连接数平均值的 1.5 倍时,认为该 Invoker 负载过高。

  3. 更新 `findLeastActiveInvoker` 方法,以实现当选择的虚拟节点不可用或者负载过高时,顺延选择集合内与原始节点离得最远的虚拟节点重新组成新集合的功能:

    private <T> Invoker<T> findLeastActiveInvoker(List<Invoker<T>> nearestInvokers, URL url, Invocation invocation) {
        // ... 当选择的虚拟节点不可用或者负载过高时,顺延选择集合内与原始节点离得最远的虚拟节点重新组成新集合的功能
    }
  4. 最后,在 Dubbo 配置中指定使用自定义负载均衡策略 CustomLoadBalance。例如,在 application.properties 文件中,可以添加以下配置:
    dubbo.consumer.loadbalance=custom
    

    或者在 XML 配置中指定:

  5. <dubbo:reference id="xxxService" interface="xxx.xxx.XxxService" loadbalance="custom" />
    

    这样,Dubbo 会在运行时使用您的自定义负载均衡策略 CustomLoadBalance,实现一致性哈希和最少活跃法的结合。这将帮助您更好地满足分布式视频流转码场景的需求,提供更加健壮和高效的负载均衡。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值