Resumen
En la última sección, cuando seleccionamos el clúster, se seleccionaron el invocador final y el método de selección de equilibrio de carga. Veamos primero el código diseñado para el equilibrio de carga en la sección anterior, la clase AbstractClusterInvoker:
El Invoker privado <T> doSelect (LoadBalance loadbalance, Invocación invocación, List <Invoker <T>> invocadores, List <Invoker <T>> seleccionado) lanza RpcException { if (CollectionUtils.isEmpty (invocadores)) { return null; } if (invokers.size () == 1) { return invokers.get (0); } // 调用 loadbalance 的 select 方法 Invoker <T> invoker = loadbalance.select (invocadores, getUrl (), invocación); ... }
Aquí están las ventajas y desventajas de varios modos de equilibrio de carga.
Analicemos varios procesos de implementación de equilibrio de carga.
Análisis de clase padre AbstractLoadBalance
public abstract class AbstractLoadBalance implementa LoadBalance { / ** * Calcule el peso de acuerdo con la proporción de tiempo de actividad del tiempo de calentamiento * el nuevo peso estará dentro de 1 (inclusive) al peso (inclusive) * * warmup: 预热 时间 * * @param uptime el tiempo de actividad en milisegundos * @param warmup el tiempo de calentamiento en milisegundos * @param pondera el peso de un invocador * @return weight que tiene en cuenta el calentamiento * / static int CalculateWarmupWeight (int uptime, int warmup, int weight) { int ww = (int) (tiempo de actividad / ((flotación) calentamiento / peso)); volver ww <1? 1: (Math.min (ww, peso)); } @Override public <T> Invoker <T> select (List <Invoker <T>> invocadores, URL URL, invocación de invocación) { if (CollectionUtils.isEmpty (invocadores)) { return null; } if (invokers.size () == 1) { return invokers.get (0); } return doSelect (invocadores, url, invocación); } resumen protegido <T> Invoker <T> doSelect (List <Invoker <T>> invocadores, URL url, invocación de invocación); / ** * Obtenga el peso de la invocación del invocador que tiene en cuenta el tiempo de calentamiento * si el tiempo de actividad está dentro del tiempo de calentamiento, * Al calcular el peso aquí, el núcleo es la proporción de tiempo de actividad / tiempo de calentamiento. Se puede saber que cuando comienza a comenzar, cuanto menor es la proporción de tiempo de actividad es menor que el peso es menor * Cuando el inicio es largo, la proporción es mayor y el peso es naturalmente mayor. . * * @param invocador el invocador * @param invocación la invocación de este invocador * @return weight * / int getWeight (Invoker <?> invocador, invocación de invocación) { int weight; URL url = invoker.getUrl (); // Multiple escenario de registro, equilibrio de carga entre varios registros. if (REGISTRY_SERVICE_REFERENCE_PATH.equals (url.getServiceInterface ())) { weight = url.getParameter (REGISTRY_KEY + "." + WEIGHT_KEY, DEFAULT_WEIGHT); } else { peso = url.getMethodParameter (invocation.getMethodName (), WEIGHT_KEY, DEFAULT_WEIGHT); if (peso> 0) { marca de tiempo larga = invoker.getUrl (). getParameter (TIMESTAMP_KEY, 0L); if (marca de tiempo> 0L) { tiempo de actividad largo = System.currentTimeMillis () - marca de tiempo; if (tiempo de actividad <0) { return 1; } // 默认 的 预热 时间 是 10 分钟 int warmup = invoker.getUrl (). GetParameter (WARMUP_KEY, DEFAULT_WARMUP); if (tiempo de actividad> 0 && tiempo de actividad <calentamiento) { } } weight = CalculateWarmupWeight ((int) uptime, warmup, weight); } } return Math.max (peso, 0); } }
RandomLoadBalance
@Oversión protegida <T> Invoker <T> doSelect (List <Invoker <T>> invocadores, URL URL, invocación de invocación) { // Número de invocadores int length = invokers.size (); // ¿Cada invocador tiene el mismo peso? booleano sameWeight = verdadero; // el peso de cada invocador int [] weights = new int [length]; // el peso del primer invocador int firstWeight = getWeight (invokers.get (0), invocation); pesos [0] = firstWeight; // La suma de pesos int totalWeight = firstWeight; for (int i = 1; i <length; i ++) { int weight = getWeight (invocadores.get (i), invocación); // guardar para uso posterior pesos [i] = peso; // Suma totalWeight + = weight; if (sameWeight && weight! = firstWeight) { sameWeight = false; } } if (totalWeight> 0 &&! sameWeight) { // If (no todos los invocadores tienen el mismo peso y al menos el peso de un invocador> 0), seleccione aleatoriamente según totalWeight. int offset = ThreadLocalRandom.current (). nextInt (totalWeight); // Devuelve un invocador basado en el valor aleatorio. / / El bucle resta el peso del proveedor de servicios del número de compensación. Cuando la compensación es menor que 0, se devuelve el Invoker correspondiente. // 举例 说明 一下 , 我们 有 servidores = [A, B, C] , pesos = [5, 3, 2] , offset = 7。 // 第 一次 循环 , offset - 5 = 2> 0 , 即 offset> 5 , // indica que no caerá en el intervalo correspondiente al servidor A. // El segundo ciclo, offset-3 = -1 <0, es decir 5 <offset <8, // indica que caerá en el intervalo correspondiente al servidor B para (int i = 0; i <longitud; i ++) { offset- = weights [i]; if (offset <0) { return invokers.get (i); } } } // Si todos los invocadores tienen el mismo valor de peso o totalWeight = 0, devuelve de manera uniforme. return invokers.get (ThreadLocalRandom .current (). nextInt (length)); }
Resumen
Los otros tipos de análisis ya no son en profundidad, y todos se basan en el algoritmo de equilibrio para obtener un invocador.
Referencias
- http://dubbo.apache.org/zh-cn/docs/source_code_guide/loadbalance.html