这版主要是拓展dubbo中的一致哈希和最少活跃优先
方案:基于 Dubbo 和 Zookeeper 的内置一致性哈希法和最少活跃法进行扩展,实现一个结合这两种策略的自定义负载均衡策略。当选择的节点不可用或负载过高时,顺延选择下一组集合。
- 首先,创建一个自定义负载均衡策略类,继承自
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 方法 } - 修改
CustomLoadBalance类中的findNearestInvokers和findLeastActiveInvoker方法,以分别调用 Dubbo 内置的一致性哈希负载均衡策略和最少活跃优先负载均衡策略。同时实现isInvokerAvailable和isInvokerOverloaded方法,以判断 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; }在
isInvokerAvailable和sInvokerOverloaded这两个方法中,我们使用了 Dubbo 提供的RpcStatus类来获取 Invoker 的活跃连接数。在isInvokerAvailable方法中,我们通过检查 Invoker 的可用状态来判断其是否可用。在isInvokerOverloaded方法中,我们比较 Invoker 的活跃连接数与集合内所有 Invoker 的活跃连接数平均值的乘积,以判断其是否负载过高。overloadThreshold参数用于设置负载过高的阈值,例如设置为 1.5 表示当 Invoker 的活跃连接数高于集合内所有 Invoker 活跃连接数平均值的 1.5 倍时,认为该 Invoker 负载过高。 -
更新 `findLeastActiveInvoker` 方法,以实现当选择的虚拟节点不可用或者负载过高时,顺延选择集合内与原始节点离得最远的虚拟节点重新组成新集合的功能:
private <T> Invoker<T> findLeastActiveInvoker(List<Invoker<T>> nearestInvokers, URL url, Invocation invocation) { // ... 当选择的虚拟节点不可用或者负载过高时,顺延选择集合内与原始节点离得最远的虚拟节点重新组成新集合的功能 } - 最后,在 Dubbo 配置中指定使用自定义负载均衡策略
CustomLoadBalance。例如,在application.properties文件中,可以添加以下配置:dubbo.consumer.loadbalance=custom或者在 XML 配置中指定:
-
<dubbo:reference id="xxxService" interface="xxx.xxx.XxxService" loadbalance="custom" />这样,Dubbo 会在运行时使用您的自定义负载均衡策略
CustomLoadBalance,实现一致性哈希和最少活跃法的结合。这将帮助您更好地满足分布式视频流转码场景的需求,提供更加健壮和高效的负载均衡。
文章介绍了如何在Dubbo中扩展内置的一致性哈希和最少活跃优先策略,创建了一个自定义负载均衡器`CustomLoadBalance`。通过这个策略,当选择的节点不可用或负载过高时,会顺延选择下一组节点。实现包括利用`ConsistentHashLoadBalance`和`LeastActiveLoadBalance`,以及`isInvokerAvailable`和`isInvokerOverloaded`方法来判断节点的可用性和负载情况。

356

被折叠的 条评论
为什么被折叠?



