[Aprende a disfrutar de Netflix] cincuenta y ocho, la cinta de comandos de equilibrio de carga: LoadBalancerCommand (a) RBI clase base

El software debe ser capaz de usar antes de su reutilización.

-> Lista de retorno columna <-
descarga Dirección: https://github.com/f641385712/netflix-learning

prefacio

Si ya sabe demasiado Netflix Hystrix, entonces no son ajenos al modo de comando Comando. Lo mismo, la cinta también se utiliza para llevar a cabo el proceso en base a modo de comando RxJava para controlar una solicitud, que es el contenido básico de este artículo se explicará: LoadBalancerCommand.


texto

modos de comando RxJava base, LoadBalancerCommandB representa la carga de comandos de equilibrio para solicitud de transferencia al equilibrador de carga ILoadBalancer. No es mucho clases, la siguiente captura de pantalla relacionado:

Aquí Insertar imagen Descripción

Uno de los más importantes fue, sin duda, LoadBalancerCommandla API, antes de eso, el primer RBI de su clase base.


ServerOperation

Esta interfaz es muy simple, se trata de una interfaz de función Functionúnica: "comer" en un servidor, un asador Observable<T>. rxjava basada en observable de apoyo

// 仅仅继承自Func1,暴露出结果泛型T
public interface ServerOperation<T> extends Func1<Server, Observable<T>> {}

Como movimiento, como un paso en la referencia LoadBalancerCommand#submit()presentado al procesamiento de comandos.


ExecutionInfo

Un POJO, en nombre de la aplicación de la información.

public class ExecutionInfo {

    private final Server server;
    // 在该Server上已经尝试过的总次数
    private final int numberOfPastAttemptsOnServer;
    // 已经尝试过的Server总个数
    private final int numberOfPastServersAttempted;

	// 构造器是私有化的。该静态方法用于创建实例
    public static ExecutionInfo create(Server server, int numberOfPastAttemptsOnServer, int numberOfPastServersAttempted) {
        return new ExecutionInfo(server, numberOfPastAttemptsOnServer, numberOfPastServersAttempted);
    }
}

Se utiliza principalmente como un parámetro para pasar ExecutionListener, de manera que la persona que llama se puede realizar para husmear información.


ExecutionInfoContext

Es LoadBalancerCommanduna clase interna, la información de registro info contexto cuando se ejecuta.

LoadBalancerCommand:

	class ExecutionInfoContext {
		// 当前Server,每次调用set方法,此值就会变哦~~~~
		// serverAttemptCount记录了当前请求已经换了几次Server了~~~
        Server      server;
        // 已经重试的Server总数(每次换台Server就+1)
        int         serverAttemptCount = 0; 
        // 这次请求的重试总数(包括相同Server,以及换Server,总之是个总数)
        int         attemptCount = 0;

        public ExecutionInfo toExecutionInfo() {
            return ExecutionInfo.create(server, attemptCount-1, serverAttemptCount-1);
        }
        public ExecutionInfo toFinalExecutionInfo() {
            return ExecutionInfo.create(server, attemptCount, serverAttemptCount-1);
        }
	}

El contexto es principalmente una solicitud de registro a la número de contexto de reintentos cuando se ejecuta, generar una final de ExecutionInfoejemplo para el oyente , el usuario puede completar la determinación de personalización (tales como una limitación: el reintento no tendría múltiples reintentos).


ExecutionContext (importante)

En cada equilibrador de carga de ejecución de inicio se crea objeto de contexto, los metadatos contienen algunos de los equilibrador de carga y los datos variables de estado.

public class ExecutionContext<T> {
	
	// 存储元数据的Map
	private final Map<String, Object> context;
	// ChildContext继承自ExecutionContext
	private final ConcurrentHashMap<Object, ChildContext<T>> subContexts;

	// 请求。requestConfig的优先级比clientConfig的高哦,具有“覆盖”效果
	private final T request;
    private final IClientConfig requestConfig;
    private final RetryHandler retryHandler;
    private final IClientConfig clientConfig;
	
	// 子上下文:它增加了一个属性ExecutionContext<T> parent;
	// 这样便可以让两个ExecutionContext关联起来
    private static class ChildContext<T> extends ExecutionContext<T> {
        private final ExecutionContext<T> parent;
        ChildContext(ExecutionContext<T> parent) {
            super(parent.request, parent.requestConfig, parent.clientConfig, parent.retryHandler, null);
            this.parent = parent;
        }
        @Override
        public ExecutionContext<T> getGlobalContext() {
            return parent;
        }
    }
	... // 省略构造器赋值
	
	// default访问权限的方法:获取子执行上下文
	// 没有就会new一个然后放在ConcurrentHashMap缓存起来。key就是obj
	ExecutionContext<T> getChildContext(Object obj) { ... }
	...
	// 获得指定name的value。一个简单的k-v而已
    public void put(String name, Object value) {
        context.put(name, value);
    }
    public Object get(String name) {
        return context.get(name);
    }
    // 先去requestConfig里找,若没找再去clientConfig里找
    public <S> S getClientProperty(IClientConfigKey<S> key) { ... }

	// 注意:子上下文ChildContext的该方法返回的是parent,所以就打通了
    public ExecutionContext<T> getGlobalContext() {
        return this;
    }
}

Por el contexto Padre, Hijo de diseño, para asegurar que cada uno listenertiene su propioExecutionContext , pero también puede ExecutionContext#getGlobalContext()ser obtenido por todas listenercontexto compartido a nivel mundial.


ExecutionListener

Los oyentes llaman equilibrador de carga en diferentes fases de ejecución.

// I:input类型,给ExecutionContext用。这样ExecutionContext#getRequest()就能拿到这个请求对象
// O:负载均衡器执行的output输出
public interface ExecutionListener<I, O> {

	// 在执行即将开始时调用。
	public void onExecutionStart(ExecutionContext<I> context) throws AbortExecutionException;
	// 当服务器被选中,请求**将在服务器上执行时**调用。
	public void onStartWithServer(ExecutionContext<I> context, ExecutionInfo info) throws AbortExecutionException;

	// 当在服务器上执行请求时接收到异常时调用(这时木有Response,只有异常信息)
	public void onExceptionWithServer(ExecutionContext<I> context, Throwable exception,  ExecutionInfo info);
	// 执行正常,有response
	public void onExecutionSuccess(ExecutionContext<I> context, O response,  ExecutionInfo info);
	// 在**所有重试**后认为请求失败时调用
	// finalException:最终的异常。有可能包装着重试时的各种异常
	public void onExecutionFailed(ExecutionContext<I> context, Throwable finalException, ExecutionInfo info);
}

Y se ha de esta interfaz ninguna realización integrada, se deja al usuario de un gancho.


ExecutionContextListenerInvoker

Se puede considerar como una clase de utilidad: para el contexto de ejecución ExecutionContextpara llamar en una variedad de ExecutionListenerellos. Funcionar muy parecido a lo familiar primavera de arranque carril SpringApplicationRunListenerspara ejecutar SpringApplicationRunListenerel oyente.

public class ExecutionContextListenerInvoker<I, O> {

	// 执行上下文
	private final ExecutionContext<I> context;
	// 执行时的监听器们
	private final List<ExecutionListener<I, O>> listeners;
	
	private final IClientConfig clientConfig;
	// key表示的是ExecutionListener实现类的全类名
	// value:IClientConfigKey。它的值是"listener." + key+ ".disabled"
	// 因为CommonClientConfigKey.valueOf()比较耗时,所以这里用了缓存
	private final ConcurrentHashMap<String, IClientConfigKey> classConfigKeyMap;
	
	... // 省略构造器
	
	
    public void onExecutionStart() {
        onExecutionStart(this.context);
    }
	public void onExecutionStart(ExecutionContext<I> context) {
		for (ExecutionListener<I, O> listener : listeners) {
			// 若这个Listener没有被禁用,那就执行它
			if (!isListenerDisabled(listener)) {
				// 请注意:这里的上下文使用的是子上下文哦
				// 所以保证了每个监听器均有一个自己的上下文,各有一份自己的数据,线程安全
				listener.onExecutionStart(context.getChildContext(listener));
			}
		}
	}
	
	... // 执行监听器其它方法的逻辑一毛一样,略

	// 判断一个监听器是否被禁用。可通过动态配置来开/关
	// "listener." + className + ".disabled":禁用
    private boolean isListenerDisabled(ExecutionListener<?, ?> listener) {
        if (clientConfig == null) {
            return false;
        } else {
            String className = listener.getClass().getName();
            IClientConfigKey key = classConfigKeyMap.get(className);
            if (key == null) {
                key = CommonClientConfigKey.valueOf("listener." + className + ".disabled");
                IClientConfigKey old = classConfigKeyMap.putIfAbsent(className, key);
                if (old != null) {
                    key = old;
                }
            }
            return clientConfig.getPropertyAsBoolean(key, false);
        }
    }
}
  1. escucha la cinta se deja a los desarrolladores involucrados en el proceso de ejecución de balanceo de carga del gancho, el más importante (sin ningún tipo de realización construida)
  2. Cada oyente ejecutado por su propio contexto, seguro para hilos
  3. Puede ser configurado por el exterior de: "listener." + className + ".disabled"una manera de desactivar la ejecución del oyente, una cierta flexibilidad para satisfacer el diseño

resumen

Sobre la cinta Load Balancing comando: LoadBalancerCommand (a) sobre la base de la clase RBI introducido por primera vez a esta parte. Este artículo es relativamente sencillo, sobre todo para los siguientes servicios, así que estad atentos.
línea que divide

declaración

El original no es fácil, no es fácil de palabra de código, gracias por su pulgar, colección, atención. 把本文分享到你的朋友圈是被允许的,但拒绝抄袭. También puede código de exploración [Izquierda / o añadir WX: fsx641385712] Los invito a unirse a la Ingeniería de Java, Arquitecto Serie aprendizaje en grupo familiar y la comunicación.
pasado destacado

Publicados 362 artículos originales · ganado elogios 531 · vistas 480 000 +

Supongo que te gusta

Origin blog.csdn.net/f641385712/article/details/105027272
Recomendado
Clasificación