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 を介したフェイルオーバーの構成は正しくありません。