1

Apache Igniteでフォールト トレランスを試しています。

私が理解できないのは、失敗したジョブを任意のノードで再試行する方法です。私の仕事は、プロセスビルダーを介してシステムプロセスとしてサードパーティツールを呼び出して計算を行うユースケースがあります。場合によってはツールが失敗することがありますが、ほとんどの場合、以前に失敗したノードを含め、任意のノードでジョブを再試行しても問題ありません。

現時点では、Ignite は以前にこのジョブを持っていなかった別のノードにジョブを再ルーティングしているようです。そのため、しばらくするとすべてのノードがなくなり、タスクは失敗します。

私が探しているのは、任意のノードでジョブを再試行する方法です。

これが私の問題を実証するためのテストです。

これが私のランダムに失敗する仕事です:

public static class RandomlyFailingComputeJob implements ComputeJob {
    private static final long serialVersionUID = -8351095134107406874L;
    private final String data;

    public RandomlyFailingComputeJob(String data) {
        Validate.notNull(data);
        this.data = data;
    }

    public void cancel() {
    }

    public Object execute() throws IgniteException {
        final double random = Math.random();
        if (random > 0.5) {
            throw new IgniteException();
        } else {
            return StringUtils.reverse(data);
        }
    }
}

以下がタスクです。

public static class RandomlyFailingComputeTask extends
        ComputeTaskSplitAdapter<String, String> {
    private static final long serialVersionUID = 6756691331287458885L;

    @Override
    public ComputeJobResultPolicy result(ComputeJobResult res,
            List<ComputeJobResult> rcvd) throws IgniteException {
        if (res.getException() != null) {
            return ComputeJobResultPolicy.FAILOVER;
        }
        return ComputeJobResultPolicy.WAIT;
    }

    public String reduce(List<ComputeJobResult> results)
            throws IgniteException {
        final Collection<String> reducedResults = new ArrayList<String>(
                results.size());
        for (ComputeJobResult result : results) {
            reducedResults.add(result.<String> getData());
        }
        return StringUtils.join(reducedResults, ' ');
    }

    @Override
    protected Collection<? extends ComputeJob> split(int gridSize,
            String arg) throws IgniteException {
        final String[] args = StringUtils.split(arg, ' ');
        final Collection<ComputeJob> computeJobs = new ArrayList<ComputeJob>(
                args.length);
        for (String data : args) {
            computeJobs.add(new RandomlyFailingComputeJob(data));
        }
        return computeJobs;
    }

}

テストコード:

    final Ignite ignite = Ignition.start();
    final String original = "The quick brown fox jumps over the lazy dog";

    final String reversed = StringUtils.join(
            ignite.compute().execute(new RandomlyFailingComputeTask(),
                    original), ' ');

ご覧のとおり、常にフェイルオーバーする必要があります。失敗の確率 != 1 なので、ある時点でタスクが正常に終了することを期待しています。

0.5 の確率しきい値と合計 3 つのノードでは、これはほとんど起こりません。のような例外が発生しclass org.apache.ignite.cluster.ClusterTopologyException: Failed to failover a job to another node (failover SPI returned null)ます。いくつかのデバッグの後、これは最終的にノードを使い果たしたためであることがわかりました。全部なくなりました。

これを処理するために自分で書くことができることを理解していFailoverSpiます。

しかし、これはちょうどいいとは思えません。

まず、これを行うのはやり過ぎのようです。
しかし、SPI は一種のグローバルなものです。ジョブごとに、再試行するかフェイルオーバーするかを決定したいと思います。これは、たとえば、呼び出しているサードパーティ ツールの終了コードに依存する場合があります。そのため、グローバル SPI を介したフェイルオーバーの構成は正しくありません。

4

1 に答える 1