cluster-容错机制:failover、failfast、failback、failsafe

原创
2021/10/08 16:55
阅读数 856

failover:故障转移

当出现失败,重试其它服务器,通常用于读操作(推荐使用)。 重试会带来更长延迟。

    protected RpcResult doInvoke(RpcInvocation invocation, List<Invoker<T>> invokers) throws Throwable {
        List<Invoker<T>> invoked = new ArrayList<>();
        Throwable recordExe = null;

        for (int i = 0; i <= retryTimes; i++) {
            //负载均衡选择Invoker
            Invoker<T> invoker = select(invocation, invokers, invoked);
            invoked.add(invoker);
            try {
                return invoker.invoke(invocation);
            } catch (Throwable e) {
                logger.warn("Failed " + i + " times, interface=" + invoker.getInterface().getName() +
                        "|method=" + invocation.getMethod().getName() + "|provider=" +
                        invoker.getProvider().getIp() + Constants.COLON + invoker.getProvider().getPort(), e);
                recordExe = e;
            }
        }
        if (recordExe != null) {
            throw recordExe;
        }
        return new RpcResult();
    }

failfast:

只发起一次调用,失败立即报错,通常用于非幂等性的写操作。 如果有机器正在重启,可能会出现调用失败 。

    protected RpcResult doInvoke(RpcInvocation invocation, List<Invoker<T>> invokers) throws Throwable {
        Invoker<T> invoker = select(invocation, invokers, new ArrayList<Invoker<T>>());
        return invoker.invoke(invocation);
    }

failback:

后台记录失败请求,定时重发。通常用于消息通知操作 不可靠,重启丢失。 可用于生产环境 Registry。

  protected RpcResult doInvoke(RpcInvocation invocation, List<Invoker<T>> invokers) {
        //select负载均衡
        Invoker<T> invoker = select(invocation, invokers, new ArrayList<Invoker<T>>());
        try {
            return invoker.invoke(invocation);
        } catch (Throwable e) {
            logger.error("Remote invoke failed, interface=" + invoker.getInterface().getName() +
                    "|method=" + invocation.getMethod().getName() + "|provider=" +
                    invoker.getProvider().getIp() + Constants.COLON + invoker.getProvider().getPort() + ", wait for retry in background", e);
            addFailed(invocation, this);
        }
        return new RpcResult();
    }

    private void addFailed(RpcInvocation invocation, ClusterHandler<T> clusterHandler) {
        if (retryFuture == null) {
            synchronized (this) {
                if (retryFuture == null) {
                    retryFuture = scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
                        @Override
                        public void run() {
                            // 定时重试
                            try {
                                retryFailed();
                            } catch (Throwable t) {
                                logger.error("Unexpected error occur at retry", t);
                            }
                        }
                    }, RETRY_FAILED_PERIOD, RETRY_FAILED_PERIOD, TimeUnit.MILLISECONDS);
                }
            }
        }
        failed.put(invocation, clusterHandler);
    }

    private void retryFailed() {
        if (failed.size() == 0) {
            return;
        }
        for (Map.Entry<RpcInvocation, ClusterHandler<?>> entry : new HashMap<>(failed).entrySet()) {
            RpcInvocation invocation = entry.getKey();
            ClusterHandler clusterHandler = entry.getValue();
            try {
                clusterHandler.handle(invocation);
                failed.remove(invocation);
            } catch (Throwable e) {
                logger.error("Failed retry to invoke method=" + invocation.getMethod().getName() + ", waiting again.", e);
            }
        }
    }

failsafe:

出现异常时,直接忽略,通常用于写入审计日志等操作。 调用信息丢失 可用于生产环境 Monitor。

    protected RpcResult doInvoke(RpcInvocation invocation, List<Invoker<T>> invokers) throws Throwable {
        //select负载均衡
        Invoker<T> invoker = select(invocation, invokers, new ArrayList<Invoker<T>>());
        try {
            return invoker.invoke(invocation);
        } catch (Throwable e) {
            //出现异常时,直接忽略
        }
        return new RpcResult();
    }
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部