[源码阅读]Motan RPC中的负载均衡算法|Random/RoundRobin/ActiveWeight/LocalFirst/ConsistentHash/ConfigurableWeight

Motan RPC框架中的六个负载均衡算法预览

Motan RPC框架中的负载均衡算法
在这里插入图片描述
6个负载均衡算法的总结:
在这里插入图片描述
RandomLoadBalance

  • 负载随机分配
  • ThreadLocalRandom提高多线程并发随机数性能

RoundRobinLoadBalance

  • 负载轮流分配
  • AtomicInteger idx 保存状态

ActiveWeightLoadBalance

  • 低并发优先
  • 避免O(N)查找极值

LocalFirstLoadBalance

  • IP筛选 本机优先
  • 退化为ActiveWeightLoadBalance

ConsistentHashLoadBalance

  • 对参数哈希
  • 虚拟节点扩充

ConfigurableWeightLoadBalance

  • 按分组配置权重,组内RoundRobinLoadBalance
  • 未配置权重则退化为RandomLoadBalance

用到的设计模式

使用SPI的策略模式

模板方法模式

AbstractLoadBalance抽象类固定流程,扩展点通过抽象方法留给子类实现
固定流程:

    @Override
    public Referer<T> select(Request request) {
   
        List<Referer<T>> referers = this.referers;
        if (referers == null) {
   
            throw new MotanServiceException(this.getClass().getSimpleName() + " No available referers for call request:" + request);
        }
        Referer<T> ref = null;
        if (referers.size() > 1) {
   
            ref = doSelect(request);

        } else if (referers.size() == 1) {
   
            ref = referers.get(0).isAvailable() ? referers.get(0) : null;
        }

        if (ref != null) {
   
            return ref;
        }
        throw new MotanServiceException(this.getClass().getSimpleName() + " No available referers for call request:" + request);
    }

扩展点留出:

    protected abstract Referer<T> doSelect(Request request);

    protected abstract void doSelectToHolder(Request request, List<Referer<T>> refersHolder);

负载均衡顶层接口

@Spi(scope = Scope.PROTOTYPE)
public interface LoadBalance<T> {
   

    void onRefresh(List<Referer<T>> referers);

    Referer<T> select(Request request);

    void selectToHolder(Request request, List<Referer<T>> refersHolder);

    void setWeightString(String weightString);

}
  • onRefresh:更新服务提供者
  • select:按照负载均衡算法选择具体的服务提供者
  • selectToHolder:按照负载均衡算个从服务提供者列表中按序批量选取服务提供者
  • setWeightString:设置权重信息

随机负载均衡算法:RandomLoadBalance

核心思想:从服务提供者列表中随机选取一个提供服务,Random 使用 AtomicLong CAS (compare-and-set)操作来更新它的seed,CAS在资源高度竞争时存在性能问题。RandomLoadBalance算法使用了ThreadLocalRandom随机类规避了Random在多线程激烈竞争下的性能问题。
ThreadLocalRandom设计有两个要点:一是通过seed是线程隔离的,不存在竞争,二是通过缓存行填充手段避免伪共享问题。

@SpiMeta(name = "random")
public class RandomLoadBalance<T> extends AbstractLoadBalance<T> {
   

    @Override
    protected Referer<T> doSelect(Request request) {
   
        List<Referer<T>> referers = getReferers();

        int idx = (int) (ThreadLocalRandom.current().nextDouble() * referers.size());
        for (int i = 0; i < referers.size(); i++) {
   
            Referer<T> ref = referers.get((i + idx) % referers.size());
            if (ref.isAvailable()) {
   
                return ref;
            }
        }
        return null;
    }

    @Override
    protected void doSelectToHolder(Request request, List<Referer<T>> refersHolder) {
   
        List<Referer<T>> referers = getReferers();

        int idx = (int) (ThreadLocalRandom.current().nextDouble() * referers.size());
        for (int i = 0; i < referers.size(); i++) {
   
            Referer<T> referer = referers.get((i + idx) % referers.size());
            if (referer.isAvailable()) {
   
                refersHolder.add(referer);
            }
        }
    }
}

轮询负载均衡算法:RoundRobinLoadBalance

核心思想:服务提供者轮流提供服务,因为要轮流提供服务,所以该算法是有状态的,需要记录上次服务提供者。RoundRobinLoadBalance算法中使用AtomicInteger类型的idx变量记录服务提供者的服务顺序,依次递增。

@SpiMeta(name = "roundrobin")
public class RoundRobinLoadBalance<T> extends AbstractLoadBalance<T> {
   

    private AtomicInteger idx = 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Exception caught when during method invocation. request:net.risesoft.rpc.itemAdmin.DocumentManager.edit4Position(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String) requestId=1771270236171928205 java.lang.reflect.InvocationTargetException: null at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.weibo.api.motan.rpc.DefaultProvider.invoke(DefaultProvider.java:64) at com.weibo.api.motan.rpc.AbstractProvider.call(AbstractProvider.java:52) at com.weibo.api.motan.transport.ProviderMessageRouter.call(ProviderMessageRouter.java:98) at com.weibo.api.motan.transport.ProviderProtectedMessageRouter.call(ProviderProtectedMessageRouter.java:75) at com.weibo.api.motan.transport.ProviderMessageRouter.handle(ProviderMessageRouter.java:93) at com.weibo.api.motan.transport.support.DefaultRpcHeartbeatFactory$HeartMessageHandleWrapper.handle(DefaultRpcHeartbeatFactory.java:98) at com.weibo.api.motan.transport.netty4.NettyChannelHandler.processRequest(NettyChannelHandler.java:155) at com.weibo.api.motan.transport.netty4.NettyChannelHandler.processMessage(NettyChannelHandler.java:133) at com.weibo.api.motan.transport.netty4.NettyChannelHandler.access$000(NettyChannelHandler.java:32) at com.weibo.api.motan.transport.netty4.NettyChannelHandler$1.run(NettyChannelHandler.java:73) at java.util.concurrent.ThreadPoolExecutor.runWorker(Threa是哪里的问题
07-14

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值