如果任何服务失败,如果使用 Completable future 调用多个服务,则停止其他服务调用
stop other service calls if using Completable future to call multiple services if any of service fails
我正在使用可完成的未来来调用多个服务调用。
CompletableFuture<Response1> future1 = CompletableFuture.supplyAsync(() -> webServiceCall1());
CompletableFuture<Response2> future2 = CompletableFuture.supplyAsync(() -> webServiceCall2());
CompletableFuture<Response3> future3 = CompletableFuture.supplyAsync(() -> webServiceCall3());
然后我正在使用:
Response1 response1 = future1.get();
Response2 response2 = future2.get();
Response3 response3 = future3.get();
// do further processing on the response
为什么我要使用这种代码???通过这样做,我能够提高性能。如果 service1 以 200 次成功并花费 3 秒的时间,service2 以 200 次成功并花费 3 秒的时间,service3 以 200 次成功并花费 3 秒的时间,因此依次调用它们将花费 9 秒的时间。但是,如果我使用上面写的内容,所有这些都将并行执行并且将在 3 秒内完成。
现在的问题是,如果 webservice1 失败,则不需要访问 webservice2 和 webservice3。但在我的场景中,由于代码是以调用 webservice2 和 webservice3 的方式编写的,即使 webservice1 失败也是如此。
我们如何才能避免这种情况并仍然保持并行 web 服务调用并且同时仍然保持故障安全??
让我换个说法——我们如何才能保持这段代码的整体性能(考虑大约 3 秒左右的基准测试)并且同时仍然保持故障安全??
您可以使用 thenApplyAsync
函数:
ResponseHolder holder = CompletableFuture.supplyAsync(ResponseHolder::new)
.thenApplyAsync(h -> h.setResponse1(webServiceCall1()))
.thenApplyAsync(h -> h.setResponse2(webServiceCall2()))
.thenApplyAsync(h -> h.setResponse3(webServiceCall3()))
.get() // may fail
;
和 ResponseHolder
class:
public class ResponseHolder {
private Response1 response1;
private Response2 response2;
private Response3 response3;
// for each responseX:
public ResponseHolder setResponse1(Response1 response1) {
this.response1 = response1;
return this;
}
}
How we can avoid this & still keep webservice calls parallel & still
fail safe at the same time ??
你不能。
当您听到服务调用 1 失败(例如)时,您已经已经开始处理 Web 服务调用 2 和 3。不打电话给他们已经太晚了。
如果你必须在服务调用1成功后才调用服务2,那么你必须等到知道服务调用1已经成功。
否则你是在求一个算命先生:现在调用服务 2 和 3,如果服务 1 在未来某个时间成功。
你能做的最好的事情是提供一种方法来取消正在进行的服务调用(即告诉他们在下一个方便的时间点退出),但这可能比获得更多的麻烦更值得对。
webServiceCall1()
无论如何都会开火
webServiceCall2()
将检查 webServiceCall1()
- 检查是否已返回 1 的响应状态
- 如果响应状态为 200,则继续并触发
- 如果响应状态不是200,请勿拨打电话
- 如果尚未返回响应状态,请继续进行调用 - 本质上,我们假设它会成功
webServiceCall3
将检查 webServiceCall1()
和 webServiceCall2()
我想强调一下 - 如果在我们尝试 webServiceCall2()
时 webServiceCall1()
尚未完成,那么我们 假设 webServiceCall1()
已返回并成功返回 200 响应代码。如果它最终 webServiceCall1()
是 not 即使在假设它成功之后,那么我们将毫无意义地调用 webServiceCall2()
(并且可能 webServiceCall3()
),所以请注意这一点。
我的解决方案 ONLY 涵盖了 webServiceCall1()
触发和失败的边缘情况,我们很快就收到了回复在我们有机会在第二个 CompletableFuture 中检查它之前。 webServiceCall2()
和第三个 CompletableFuture 相同。在这两种情况下,我们都会优化掉 1 或 2 个调用。但是不要假设这会发生每次次webServiceCall1()
或webServiceCall2()
失败。
CompletableFuture<Response1> future1 = CompletableFuture.supplyAsync(() -> webServiceCall1());
CompletableFuture<Response2> future2 = CompletableFuture.supplyAsync(() -> (performServiceCheck(future1) ? webServiceCall2() : null));
CompletableFuture<Response3> future3 = CompletableFuture.supplyAsync(() -> (performServiceCheck(future1, future2) ? webServiceCall3() : null));
private boolean performServiceCheck(CompletableFuture<?> ...futures) {
boolean result = true;
for (CompletableFuture<?> future : futures) {
if (future.isDone() && is200(future.get())) {
result = result && true;
} else if (future.isDone() && !is200(future.get())) {
result = result && false;
} else if (!future.isDone()) {
result = result && true;
}
}
return result;
}
我正在使用可完成的未来来调用多个服务调用。
CompletableFuture<Response1> future1 = CompletableFuture.supplyAsync(() -> webServiceCall1());
CompletableFuture<Response2> future2 = CompletableFuture.supplyAsync(() -> webServiceCall2());
CompletableFuture<Response3> future3 = CompletableFuture.supplyAsync(() -> webServiceCall3());
然后我正在使用:
Response1 response1 = future1.get();
Response2 response2 = future2.get();
Response3 response3 = future3.get();
// do further processing on the response
为什么我要使用这种代码???通过这样做,我能够提高性能。如果 service1 以 200 次成功并花费 3 秒的时间,service2 以 200 次成功并花费 3 秒的时间,service3 以 200 次成功并花费 3 秒的时间,因此依次调用它们将花费 9 秒的时间。但是,如果我使用上面写的内容,所有这些都将并行执行并且将在 3 秒内完成。
现在的问题是,如果 webservice1 失败,则不需要访问 webservice2 和 webservice3。但在我的场景中,由于代码是以调用 webservice2 和 webservice3 的方式编写的,即使 webservice1 失败也是如此。
我们如何才能避免这种情况并仍然保持并行 web 服务调用并且同时仍然保持故障安全??
让我换个说法——我们如何才能保持这段代码的整体性能(考虑大约 3 秒左右的基准测试)并且同时仍然保持故障安全??
您可以使用 thenApplyAsync
函数:
ResponseHolder holder = CompletableFuture.supplyAsync(ResponseHolder::new)
.thenApplyAsync(h -> h.setResponse1(webServiceCall1()))
.thenApplyAsync(h -> h.setResponse2(webServiceCall2()))
.thenApplyAsync(h -> h.setResponse3(webServiceCall3()))
.get() // may fail
;
和 ResponseHolder
class:
public class ResponseHolder {
private Response1 response1;
private Response2 response2;
private Response3 response3;
// for each responseX:
public ResponseHolder setResponse1(Response1 response1) {
this.response1 = response1;
return this;
}
}
How we can avoid this & still keep webservice calls parallel & still fail safe at the same time ??
你不能。
当您听到服务调用 1 失败(例如)时,您已经已经开始处理 Web 服务调用 2 和 3。不打电话给他们已经太晚了。
如果你必须在服务调用1成功后才调用服务2,那么你必须等到知道服务调用1已经成功。
否则你是在求一个算命先生:现在调用服务 2 和 3,如果服务 1 在未来某个时间成功。
你能做的最好的事情是提供一种方法来取消正在进行的服务调用(即告诉他们在下一个方便的时间点退出),但这可能比获得更多的麻烦更值得对。
webServiceCall1()
无论如何都会开火webServiceCall2()
将检查webServiceCall1()
- 检查是否已返回 1 的响应状态
- 如果响应状态为 200,则继续并触发
- 如果响应状态不是200,请勿拨打电话
- 如果尚未返回响应状态,请继续进行调用 - 本质上,我们假设它会成功
- 检查是否已返回 1 的响应状态
webServiceCall3
将检查webServiceCall1()
和webServiceCall2()
我想强调一下 - 如果在我们尝试 webServiceCall2()
时 webServiceCall1()
尚未完成,那么我们 假设 webServiceCall1()
已返回并成功返回 200 响应代码。如果它最终 webServiceCall1()
是 not 即使在假设它成功之后,那么我们将毫无意义地调用 webServiceCall2()
(并且可能 webServiceCall3()
),所以请注意这一点。
我的解决方案 ONLY 涵盖了 webServiceCall1()
触发和失败的边缘情况,我们很快就收到了回复在我们有机会在第二个 CompletableFuture 中检查它之前。 webServiceCall2()
和第三个 CompletableFuture 相同。在这两种情况下,我们都会优化掉 1 或 2 个调用。但是不要假设这会发生每次次webServiceCall1()
或webServiceCall2()
失败。
CompletableFuture<Response1> future1 = CompletableFuture.supplyAsync(() -> webServiceCall1());
CompletableFuture<Response2> future2 = CompletableFuture.supplyAsync(() -> (performServiceCheck(future1) ? webServiceCall2() : null));
CompletableFuture<Response3> future3 = CompletableFuture.supplyAsync(() -> (performServiceCheck(future1, future2) ? webServiceCall3() : null));
private boolean performServiceCheck(CompletableFuture<?> ...futures) {
boolean result = true;
for (CompletableFuture<?> future : futures) {
if (future.isDone() && is200(future.get())) {
result = result && true;
} else if (future.isDone() && !is200(future.get())) {
result = result && false;
} else if (!future.isDone()) {
result = result && true;
}
}
return result;
}