WLPs MicroProfile (FaultTolerance) Тайм-аут Реализация не прерывает потоки? - PullRequest
0 голосов
/ 20 сентября 2018

Я тестирую реализацию отказоустойчивости (микропрофиля) 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);
    }
}

1 Ответ

0 голосов
/ 20 сентября 2018

Он прерывает потоки, используя Thread.interrupt(), но, к сожалению, не все операции Java реагируют на прерывания потока.

Многие вещи реагируют на прерывания, генерируя исключение InterruptedException (например, Thread.sleep(), Object.wait(),Future.get() и подклассы InterruptableChannel), но InputStreams и Sockets этого не делают.

Я подозреваю, что вы (или библиотека, которую вы используете для выполнения запроса) используете Socket, который не прерываетсяпоэтому вы не видите, чтобы ваш метод возвращался рано.

Это особенно не интуитивно понятно, потому что клиент Liberty JAX-RS не отвечает на прерывания потоков, как упоминал Энди МакКрайт.Мы знаем, что это не очень хорошая ситуация, и мы работаем над тем, чтобы улучшить ее.

...