Я тестирую реализацию отказоустойчивости (микропрофиля) websphere liberty.Поэтому я сделал простой REST-сервис с ресурсом, который спит 5 секунд:
@Path("client")
public class Client {
@GET
@Path("timeout")
public Response getClientTimeout() throws InterruptedException {
Thread.sleep(5000);
return Response.ok().entity("text").build();
}
}
Я вызываю этого клиента в том же приложении в другом REST-сервисе:
@Path("mpfaulttolerance")
@RequestScoped
public class MpFaultToleranceController {
@GET
@Path("timeout")
@Timeout(4)
public Response getFailingRequest() {
System.out.println("start");
// calls the 5 seconds-ressource; should time out
Response response = ClientBuilder.newClient().target("http://localhost:9080").path("/resilience/api/client/timeout").request().get();
System.out.println("hello");
}
}
СейчасЯ ожидал бы, что метод getFailingRequest () истечет через 4 мсек и выдаст исключение.Фактическое поведение заключается в том, что приложение печатает «start», ждет 5 секунд, пока клиент не вернется, печатает «hello», а затем выдает «org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException».
Я повернулсядля дальнейшей отладочной информации:
<logging traceSpecification="com.ibm.ws.microprofile.*=all" />
в server.xml.Я получаю эту информацию, что время ожидания зарегистрировано даже до того, как клиент называется!Но поток не прерывается.
(если кто-то подскажет мне, как получить красивую трассировку стека ... я могу это сделать.)
Поскольку это очень простой пример:делать что-то не так здесь?Что я могу сделать, чтобы этот пример работал правильно.
Спасибо
Редактировать: Запуск этого примера на WebSphere Application Server 18.0.0.2/wlp-1.0.21.cl180220180619-0403) auf Java HotSpot(TM) 64-разрядная серверная виртуальная машина версии 1.8.0_172-b11 (de_DE) с функциями webProfile-8.0, mpFaultTolerance-1.0 и localConnector-1.0.
Редактировать: Решение благодаря Энди МакКрайту и Azquelt.Поскольку вызов не может быть прерван, я должен сделать его асинхронным.Итак, вы получили 2 потока: первый, который вызывает второй поток с вызовом.Первый поток будет прерван, второй останется до завершения вызова.Но теперь вы можете продолжить обработку сбоев, открыть цепь и все в таком духе, чтобы предотвратить дальнейшие вызовы сломанной службы.
@Path("mpfaulttolerance")
@RequestScoped
public class MpFaultToleranceController {
@Inject
private TestBase test;
@GET
@Path("timeout")
@Timeout(4)
public Response getFailingRequest() throws InterruptedException, ExecutionException {
Future<Response> resp = test.createFailingRequestToClientAsynch();
return resp.get();
}
}
И клиентский вызов:
@ApplicationScoped
public class TestBase {
@Asynchronous
public Future<Response> createFailingRequestToClientAsynch() {
Response response = ClientBuilder.newClient().target("http://localhost:9080").path("/resilience/api/client/timeout").request().get();
return CompletableFuture.completedFuture(response);
}
}