1. 程式人生 > >dubbo 叢集容錯模式原始碼學習 -- FaibackCluster

dubbo 叢集容錯模式原始碼學習 -- FaibackCluster

#FailbackCluster
當呼叫失敗後,將呼叫失敗的請求放在failed 集合。這個集合是併發訪問,所有的請求失敗的都會放在這個結合中。之後,通過scheduledExecutorService 去定時從新執行這些失敗的請求,只要failed 集合有元素,就會執行。

public class FailbackCluster {

private volatile ScheduledFuture<?> retryFuture; // retryFuture 是隻讀的,所以用volatile.
private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
private final List<Node> failed = new CopyOnWriteArrayList<>();


void failbackCluster() {
    Node node = selectOneNode();
    try {
        String resp = node.doSomething();
    }catch (Throwable e) {
        System.out.println("Node perform failed. will retry in background." + e.getMessage());
        addFailed(node);
    }
}

private Node selectOneNode() {
    // 使用負載均衡選擇出一個節點相應
    return new Node(1);
}

private void addFailed(Node node) {
    if (retryFuture == null) {
        synchronized (this) {
            if (retryFuture == null) { // 二次判斷 retry 是否為空, 防止 update on read error.
                scheduledExecutorService.scheduleAtFixedRate(new Runnable() { // 定時重試任務
                    @Override
                    public void run() {
                        try {
                            retryFailed();
                        }catch (Throwable t) {
                            System.out.print("retry failed.");
                        }
                    }
                }, 5000, 5000, TimeUnit.MILLISECONDS);
            }
        }
    }
}

private void retryFailed() {
    if (failed.size() == 0) {
        return;
    }
    for (Node n : failed) {
        try {
            n.doSomething();
            failed.remove(n);
        }catch (Throwable t) {
            System.out.println("Failed to retry node.doSomething" + t.getMessage());
        }
    }
}

class Node {
    private int id;

    Node(int id) {
        this.id = id;
    }

    String doSomething() {
        return "Node " + id + "第一個完成響應";
    };
}

}