概観
前のセクションでは、クラスターを選択したときに、最後の呼び出し元と負荷分散の選択方法が選択されました。まず、前のセクションでAbstractClusterInvokerクラスを負荷分散するように設計されたコードを見てみましょう。
Private Invoker <T> doSelect(LoadBalance loadbalance、Invocation invocation、 List <Invoker <T >> invokers、List <Invoker <T >> selected)はRpcException { if(CollectionUtils.isEmpty(invokers)){ return null; } if(invokers.size()== 1){ return invokers.get(0); } //ロードバランスを選択しますselectメソッド Invoker <T> invoker = loadbalance.select(invokers、getUrl()、invocation); ... }
いくつかのロードバランシングモードの利点と欠点を次に示します。
いくつかの負荷分散実装プロセスを分析してみましょう。
AbstractLoadBalance親クラス分析
パブリック抽象クラスAbstractLoadBalanceはLoadBalanceを実装します{ / ** *ウォームアップ時間の稼働時間の比率に従ってウェイトを計算します *新しいウェイトは、ウェイト(包括的)から1(包括的)以内になります * *ウォームアップ:预热 時間间 * * @paramアップタイムミリ秒単位 のアップタイム * @param warmup ミリ秒単位のウォームアップ時間* @param weight呼び出し元のウェイト*ウォームアップを考慮した@returnウェイト * / static int calculateWarmupWeight(int uptime、int warmup、int weight){ int ww = (int)(稼働時間/((float)ウォームアップ/重量)); 戻りww <1?1:(Math.min(ww、体重)); } @Override public <T> Invoker <T> select(List <Invoker <T >> invokers、URL url、Invocation invocation){ if(CollectionUtils.isEmpty(invokers)){ return null; } if(invokers.size()== 1){ return invokers.get(0); } return doSelect(invokers、url、invocation); } protected abstract <T> Invoker <T> doSelect(List <Invoker <T >> invokers、URL url、Invocation invocation); / ** *ウォームアップ時間を考慮した呼び出し元の呼び出しの重みを取得します *アップタイムがウォームアップ時間内にある場合、 *ここでウェイトを計算する場合、コアは稼働時間/ウォームアップ時間の比率です。始動を開始すると、稼働時間の比率が小さいほど、ウェイトよりも小さいことがわかります。 *起動が長い場合、比率が大きく、ウェイトは当然大きくなります。 。 * * @param invoker呼び出し元 * @param invocationこの呼び出し元の呼び出し * @return weight * / int getWeight(Invoker <?> invoker、Invocation invocation){ int weight; URL url = invoker.getUrl(); //複数レジストリシナリオ、複数のレジストリ間の負荷分散 if(REGISTRY_SERVICE_REFERENCE_PATH.equals(url.getServiceInterface())){ weight = url.getParameter(REGISTRY_KEY + "。" + WEIGHT_KEY、DEFAULT_WEIGHT); } else { weight = url.getMethodParameter(invocation.getMethodName()、WEIGHT_KEY、DEFAULT_WEIGHT); if(weight> 0){ long timestamp = invoker.getUrl()。getParameter(TIMESTAMP_KEY、0L); if(timestamp> 0L){ long uptime = System.currentTimeMillis()-タイムスタンプ; if(uptime <0){ return 1; } // 10分の认 int warmup = invoker.getUrl()。getParameter(WARMUP_KEY、DEFAULT_WARMUP); if(uptime> 0 && uptime <warmup){ } } weight = calculateWarmupWeight((int)uptime、warmup、weight); } } Math.max(weight、0);を返します。 } }
RandomLoadBalance
@Override protected <T> Invoker <T> doSelect(List <Invoker <T >> invokers、URL url、Invocation invocation){ // 呼び出し元の数 int length = invokers.size(); //すべての呼び出し元の重みは同じですか? boolean sameWeight = true; //すべての呼び出し元の 重みint [] weights = new int [length]; //最初の呼び出し元の重み int firstWeight = getWeight(invokers.get(0)、invocation); weights [0] = firstWeight; //ウェイトの合計 int totalWeight = firstWeight; for(int i = 1; i <length; i ++){ int weight = getWeight(invokers.get(i)、invocation); //後で使用するために保存 weights [i] =重み; // sumTotalWeight + = weight; if(sameWeight && weight!= firstWeight){ sameWeight = false; } } if(totalWeight> 0 &&!sameWeight){ //(すべての呼び出し元が同じ重みでなく、少なくとも1つの呼び出し元の重み> 0でない場合)、totalWeightに基づいてランダムに選択します。 intオフセット= ThreadLocalRandom.current()。nextInt(totalWeight); //ランダムな値に基づいて呼び出し元を返します。 / /ループは、オフセット番号からサービスプロバイダーの重みを減算します。オフセットが0未満の場合、対応するInvokerが返されます。 //例の説明一次、我们有サーバー= [A、B、C]、重み= [ 5、3、2 ]、オフセット=7 。//第一次循環环、オフセット-5 = 2> 0、即オフセット> 5、 //サーバーAに対応する間隔に該当しないことを示します。 // 2番目のサイクル、offset-3 = -1 <0、つまり5 <offset <8、 //は、サーバーBに対応する間隔に該当することを示します (int i = 0; i <length; i ++){ offset- = weights [i]; if(offset <0){ return invokers.get(i); } } } //すべての呼び出し元が同じ重み値またはtotalWeight = 0の場合、均等に 返します。return invokers.get(ThreadLocalRandom .current()。nextInt(length)); }
まとめ
他のタイプの分析は詳細ではなくなり、呼び出し元を取得するための平衡アルゴリズムにすべて基づいています。
参考文献
- http://dubbo.apache.org/zh-cn/docs/source_code_guide/loadbalance.html