Cluster 层
集群容错层、该层中包含 Cluster、Directory、Router、LoadBalance几大核心接口
网络异常,图片无法展示
|
网络异常,图片无法展示
|
这个版本有 10 种容错机制
每个具体的 Cluster 实现都是创建一个对应的 Invoker、然后直接返回
Failover
网络异常,图片无法展示
|
网络异常,图片无法展示
|
list(invocation)
从 Directory 中获取提供者的列表initLoadBalance(invokers, invocation);
选择出负载均衡策略doInvoke(invocation, invokers, loadbalance)
调用子类具体实现
很明显、这个是一个模板方法
网络异常,图片无法展示
|
checkInvokers(copyInvokers, invocation)
判断 Invoker 列表是否为空、为空则抛出异常int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
获取用户配置的重试次数、如果没有则默认是重试 2 次、这里 +1 是因为正常调用invoked
变脸用于存储已经发起调用过的 Invoker、也就是存在于这个集合里面的、都是调用过发生RPC异常的- 当你第一次调用失败之后、那么每一次循环都会重新从 Diretory 中获取最新的 Invoker 列表、因为调用次数是死的、已经失败过一次了、尽可能保证被调用的 Invoker 的质量
select(loadbalance, invocation, copyInvokers, invoked)
根据具体的负载均衡算法算出一个 Invoker
Failfast
网络异常,图片无法展示
|
Failsafe
网络异常,图片无法展示
|
Failback
网络异常,图片无法展示
|
网络异常,图片无法展示
|
这个后续的调度重试涉及到时间轮的设计、但是我们在这里只要知道它也会重试、这里默认重试的次数是三次
Forking
同时调用多个相同的服务、只要其中一个返回、则立即返回结果。用户可以配置 forking 参数、来确定最大并行调用的服务数量。
通常使用在对接口实时性要求极高的调用上、但会浪费更多的资源
@Override @SuppressWarnings({"unchecked", "rawtypes"}) public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException { try { checkInvokers(invokers, invocation); final List<Invoker<T>> selected; final int forks = getUrl().getParameter(FORKS_KEY, DEFAULT_FORKS); final int timeout = getUrl().getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT); if (forks <= 0 || forks >= invokers.size()) { selected = invokers; } else { selected = new ArrayList<>(forks); while (selected.size() < forks) { Invoker<T> invoker = select(loadbalance, invocation, invokers, selected); if (!selected.contains(invoker)) { //Avoid add the same invoker several times. selected.add(invoker); } } } RpcContext.getContext().setInvokers((List) selected); final AtomicInteger count = new AtomicInteger(); final BlockingQueue<Object> ref = new LinkedBlockingQueue<>(); for (final Invoker<T> invoker : selected) { executor.execute(() -> { try { Result result = invoker.invoke(invocation); ref.offer(result); } catch (Throwable e) { int value = count.incrementAndGet(); if (value >= selected.size()) { ref.offer(e); } } }); } try { Object ret = ref.poll(timeout, TimeUnit.MILLISECONDS); if (ret instanceof Throwable) { Throwable e = (Throwable) ret; throw new RpcException(""); } return (Result) ret; } catch (InterruptedException e) { throw new RpcException("Failed to forking invoke provider " + selected + ", but no luck to perform the invocation. Last error is: " + e.getMessage(), e); } } finally { // clear attachments which is binding to current thread. RpcContext.getContext().clearAttachments(); } } 复制代码
默认最大的并行数是 2 个、超时时间是 1 秒。
第一步就是选出合适的 invoker、根据负载均衡算法。如果 forking 的数量大于等于 invoker 的数量、那么就直接不用选了
后续使用线程池异步发起调用、使用 BlockingQueue 对存储结果。最后使用 poll 等待结果、
Broadcast
广播调用所有可用服务、任意一个节点报错则报错。因为请求是调用所以节点、所以不需要做负载均衡
网络异常,图片无法展示
|
Mock
提供者调用失败时、返回伪造的响应结果。或直接强制返回伪造结果、不会发起远程调用
网络异常,图片无法展示
|
- 默认情况下、或者明确配置了 false、那么直接调用 invoker
- 配置了 force 开头、那么直接走 mock 逻辑(相当于熔断了)
- 除了上面的情况、invoker 失败或者异常的情况下、走 mock (相当于降级)
Available
网络异常,图片无法展示
|
Mergeable
自动把多个节点请求得到的结果进行合并
网络异常,图片无法展示
|
网络异常,图片无法展示
|
网络异常,图片无法展示
|
调用所有的 invoker、设置为异步调用。后续对返回的结果进行处理合并
内置的合并器
网络异常,图片无法展示
|
Zone
这个是新版本家的一个集群策略、主要是真的注册中心的负载、也即是对多注册中心进行负载均衡
网络异常,图片无法展示
|
网络异常,图片无法展示
|
- 如果该 Invoker 中有 preferred 值为 true 、那么就直接选该注册中心
- 如果消费者和服务注册中心注册地址是在同一个 zone 的话、那么优先选择该服务注册中心
- 如果都没有配置、那么就根据负载均衡算法选出一个