有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java WLPs微文件(容错)超时实现不中断线程?

我正在测试WebSphereLiberty的容错(微文件)实现。因此,我使用ressource提供了一个简单的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.microfile.faulttolerance.exceptions.TimeoutException”

我打开了进一步的调试信息:

<logging traceSpecification="com.ibm.ws.microprofile.*=all" />

在服务器中。xml。我得到了这些信息,即使客户端被调用,超时也会被注册!但这条线并没有中断

(如果有人告诉我怎么把stacktrace弄进来……我可以做到。)

因为这是一个非常基本的例子:我在这里做错了什么吗?我该怎么做才能使这个例子正常运行呢

谢谢

编辑:在WebSphereApplicationServer18.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的功能

编辑:解决方案,感谢Andy McRight和Azquelt。 由于呼叫无法中断,我必须使其异步。因此您有两个线程:第一个线程调用第二个线程。第一个线程将被中断,第二个线程将一直保持到调用完成。但是现在你可以继续处理故障,打开电路之类的东西,以防止对坏掉的服务进行进一步的呼叫

@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);
    }
}

共 (2) 个答案

  1. # 1 楼答案

    它确实使用Thread.interrupt()中断线程,但不幸的是,并非所有Java操作都响应线程中断

    很多事情都会通过抛出InterruptedException(比如Thread.sleep()Object.wait()Future.get()InterruptableChannel的子类)来响应中断,但InputStreams和Socket不会

    我怀疑您(或您用来发出请求的库)正在使用一个不可中断的套接字,因此您不会看到您的方法提前返回

    它特别不直观,因为Liberty的JAX-RS客户端不会像Andy McRight提到的那样响应线程中断。我们意识到这不是一个很好的情况,我们正在努力使它变得更好

  2. # 2 楼答案

    我也有同样的问题。对于我使用的一些URL,容错超时不起作用。 在我的例子中,我使用RestClient。我使用RestClientBuilder的readTimeout()解决了我的问题:

    MyRestClientClass myRestClientClass = RestClientBuilder.newBuilder().baseUri(uri).readTimeout(3l, TimeUnit.SECONDS) .build(MyRestClientClient.class); 
    

    使用此超时控件的一个优点是可以将超时作为参数传递