WLPs MicroProfile (FaultTolerance) 超时实现不中断线程?
WLPs MicroProfile (FaultTolerance) Timeout Implementation does not interrupt threads?
我正在测试 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 秒,直到客户端 returns,打印 "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 位服务器 VM,版本 1.8 .0_172-b11 (de_DE) 具有 webProfile-8.0、mpFaultTolerance-1.0 和 localConnector-1.0 功能。
编辑:解决方案,感谢 Andy McCright 和 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);
}
}
它确实使用 Thread.interrupt()
中断线程,但不幸的是,并非所有 Java 操作都响应线程中断。
很多东西确实通过抛出 InterruptedException(如 Thread.sleep()
、Object.wait()
、Future.get()
和 InterruptableChannel
的子类)来响应中断,但 InputStreams 和 Sockets 不会t.
我怀疑您(或您用来发出请求的库)使用的是不可中断的套接字,因此您没有提前看到您的方法return。
这特别不直观,因为 Liberty 的 JAX-RS 客户端不会像 Andy McCright 提到的那样响应线程中断。我们知道这不是一个很好的情况,我们正在努力让它变得更好。
我遇到了同样的问题。对于我使用的某些 URL,容错超时不起作用。
就我而言,我使用 RestClient。我使用 RestClientBuilder 的 readTimeout() 解决了我的问题:
MyRestClientClass myRestClientClass = RestClientBuilder.newBuilder().baseUri(uri).readTimeout(3l, TimeUnit.SECONDS) .build(MyRestClientClient.class);
使用此超时控件的一个优点是您可以将超时作为参数传递。
我正在测试 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 秒,直到客户端 returns,打印 "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 位服务器 VM,版本 1.8 .0_172-b11 (de_DE) 具有 webProfile-8.0、mpFaultTolerance-1.0 和 localConnector-1.0 功能。
编辑:解决方案,感谢 Andy McCright 和 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);
}
}
它确实使用 Thread.interrupt()
中断线程,但不幸的是,并非所有 Java 操作都响应线程中断。
很多东西确实通过抛出 InterruptedException(如 Thread.sleep()
、Object.wait()
、Future.get()
和 InterruptableChannel
的子类)来响应中断,但 InputStreams 和 Sockets 不会t.
我怀疑您(或您用来发出请求的库)使用的是不可中断的套接字,因此您没有提前看到您的方法return。
这特别不直观,因为 Liberty 的 JAX-RS 客户端不会像 Andy McCright 提到的那样响应线程中断。我们知道这不是一个很好的情况,我们正在努力让它变得更好。
我遇到了同样的问题。对于我使用的某些 URL,容错超时不起作用。 就我而言,我使用 RestClient。我使用 RestClientBuilder 的 readTimeout() 解决了我的问题:
MyRestClientClass myRestClientClass = RestClientBuilder.newBuilder().baseUri(uri).readTimeout(3l, TimeUnit.SECONDS) .build(MyRestClientClient.class);
使用此超时控件的一个优点是您可以将超时作为参数传递。