[Aprenda a apreciar Netflix] cinquenta e oito, fita comando de balanceamento de carga: LoadBalancerCommand (a) classe base RBI

O software deve ser capaz de usar antes de reutilizar.

-> retorno Lista coluna <-
Download Endereço: https://github.com/f641385712/netflix-learning

prefácio

Se você já sabe muito Netflix Hystrix, então você não é estranho para o modo de comando de comando. O mesmo, fita também utilizado para realizar o processo com base no modo de comando RxJava para controlar um pedido, que é o conteúdo central deste artigo irá explicar: LoadBalancerCommand.


texto

modos de comando baseadas RxJava, LoadBalancerCommandB representa a carga comando de equilíbrio para pedido de transferência para o equilibrador de carga ILoadBalancer. Não está muito relacionado classes, a tela a seguir:

Aqui Insert Picture Descrição

Um dos mais importante foi, sem dúvida, LoadBalancerCommando API, antes disso, o primeiro RBI da sua classe base.


ServerOperation

Esta interface é muito simples, é uma interface de função Functionapenas: "comer" em um servidor, um espeto Observable<T>. rxjava observável à base de apoio

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

Como um movimento, como uma passagem para a referência LoadBalancerCommand#submit()submetidos ao processamento de comandos.


ExecutionInfo

Um POJO, em nome da implementação da informação.

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);
    }
}

É usado principalmente como um parâmetro para passar ExecutionListener, de modo que o chamador pode ser realizada para bisbilhotar informações.


ExecutionInfoContext

É LoadBalancerCommanduma classe interna, o contexto informações registro info quando executado.

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);
        }
	}

O contexto é principalmente um pedido de gravao para o número de contexto de novas tentativas, quando executadas, gerar uma última ExecutionInfoinstância para o ouvinte , o utilizador pode completar a determinação personalização (tal como uma limitação: a repetição não teria várias tentativas).


ExecutionContext (importante)

Em cada um balanceador de carga de execução início objeto de contexto é criado, os metadados contém alguns dos balanceador de carga e os dados variáveis 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;
    }
}

Pelo contexto Pai, Filho do design, para garantir que cada um listenertem o seu próprioExecutionContext , mas você também pode ExecutionContext#getGlobalContext()ser obtida para todos listenercontexto global compartilhado.


ExecutionListener

Ouvintes ligam balanceador de carga em diferentes estágios de implementação.

// 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);
}

E não construiu-realização para esta interface, é deixado para o usuário de um gancho.


ExecutionContextListenerInvoker

Ele pode ser considerado uma classe de utilitário: para o contexto de execução ExecutionContextpara chamar em uma variedade de ExecutionListener-los. Funcionar muito parecido com o familiar Primavera Bota pista SpringApplicationRunListenerspara executar SpringApplicationRunListenero ouvinte.

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. ouvinte fita é deixada para os desenvolvedores envolvidos no processo de execução de balanceamento de carga gancho, o mais importante (sem qualquer built-realização)
  2. Cada ouvinte executado por seu contexto próprio, o segmento de seguros
  3. Pode ser configurado pelo externamente: "listener." + className + ".disabled"uma maneira de desativar a execução do ouvinte, uma certa flexibilidade para atender o projeto

resumo

Sobre carregar a fita de comando Equilíbrio: LoadBalancerCommand (a) com base na classe RBI introduzido pela primeira vez a esta parte. Este artigo é relativamente simples, principalmente para os seguintes serviços, portanto, fique atento.
linha divisória

afirmação

O original não é fácil, não é fácil de palavra de código, muito obrigado pela sua polegares, coleção, atenção. 把本文分享到你的朋友圈是被允许的,但拒绝抄袭. Você também pode código de verificação [para a esquerda / ou adicionar wx: fsx641385712] Eu convido você para participar da Engenharia Java, Architect Series aprendizagem em grupo familiar e comunicação.
passado em destaque

Publicado 362 artigos originais · Louvor obteve 531 · vista 480 000 +

Acho que você gosta

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