resttemplate的默认httpclient,读取超时具有绝对值

时间:2019-05-20 12:28:01

标签: java spring spring-boot

我遇到了一个问题,即应用程序在使用Spring Boot的RestTemplate进行的后期调用中无限期地阻塞。

ResponseEntity<String> response = restTemplate.postForEntity(destination.getUri(), request, String.class);

我们使用默认的标准JDK实现,并按以下方式创建它:

    this.restTemplate = restTemplateBuilder
                       .setConnectTimeout(5000)
                       .setReadTimeout(5000)
                       .build();

将连接和读取超时设置为5秒。但这似乎不是一个绝对值,一旦我们的应用程序收到一些字节,此读取超时就会重置,这将导致我们的应用程序无限期地等待。

我宁愿有一个绝对的读取超时,如果您在不到5秒钟的时间内没有收到最终响应,则模板会抛出TimeoutException

我在默认客户端的选项中找不到类似的内容吗?

---编辑---

我尝试了@Peekay答案,但似乎不起作用:

    CloseableHttpClient httpClient = HttpClientBuilder.create()
           .setConnectionTimeToLive(1, TimeUnit.SECONDS)
           .setConnectionManager(new PoolingHttpClientConnectionManager())
           .build();

   HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
   clientHttpRequestFactory.setHttpClient(httpClient);
   return new RestTemplate(clientHttpRequestFactory);

我还尝试了客户端RestTemplate的不同实现,例如HttpComponentsClientHttpNetty4ClientOkHttp3Client像这样创建它们:

    Netty4ClientHttpRequestFactory factory = new Netty4ClientHttpRequestFactory();
    factory.setConnectTimeout(timeout);
    factory.setReadTimeout(readTimeout);
    return new RestTemplate(factory);

并在响应时间超过5秒的情况下对其进行了测试。除了Netty返回ReadTimeoutException以外,所有其他人都返回了200成功。不幸的是,我无法切换到该客户端,如果您想继续使用默认客户端,则似乎需要自己实现。

4 个答案:

答案 0 :(得分:1)

是的,您不能设置绝对值,而必须中断胎面本身。

答案 1 :(得分:1)

meow.setOnClickListener((view) ->{
            Random random = new Random();
            int r = random.nextInt(6-1) + 1;
            Toast.makeText(MainActivity.this,Integer.valueOf(r).toString(),Toast.LENGTH_SHORT).show();
            try{
                if(r==1)
                    fileDescriptor = MainActivity.this.getResources().openRawResourceFd(R.raw.meowcat1);
                else if (r==2)
                    fileDescriptor = MainActivity.this.getResources().openRawResourceFd(R.raw.meowcat2);
                else if (r==3)
                    fileDescriptor = MainActivity.this.getResources().openRawResourceFd(R.raw.meowcat3);
                else if (r==4)
                    fileDescriptor = MainActivity.this.getResources().openRawResourceFd(R.raw.meowcat4);
                else
                    fileDescriptor = MainActivity.this.getResources().openRawResourceFd(R.raw.meowcat5);
                mp.setDataSource(fileDescriptor.getFileDescriptor(), fileDescriptor.getStartOffset(), fileDescriptor.getLength());
                mp.prepare();
                mp.start();
            }catch(Exception e){e.printStackTrace();}
        });

https://howtodoinjava.com/spring-boot2/resttemplate/resttemplate-timeout-example/

答案 2 :(得分:0)

您可以将其他http客户端与RestTemplate一起使用,例如Apache HttpClient,它可以使您更好地控制如何设置,池化和维护连接:

  • 在其listprice = browser.find_element_by_xpath("//span[@class='title price']") price = listprice.text print(price) 中,您可以设置连接生存时间,即连接的最大TTL。
  • 您可以定义一个AttributeError: 'NoneType' object has no attribute 'text' 来指定一个连接超时(等待建立连接的最长时间)和一个单独的 socket超时(最大时间) read()将等待数据。)

有关更多详细信息,请参见:setConnectTimeout vs. setConnectionTimeToLive vs. setSocketTimeout()

答案 3 :(得分:0)

我们解决此问题的方法是将RestTemplate REST调用包装在CompletableFuture中,并使用包装器中的超时功能杀死线程,如果它花费的时间太长。

这里是一个例子:

CompletableFuture<T> requestWrapper = CompletableFuture.supplyAsync(() -> {
  return restTemplate.postForEntity(/* Whatever arguments you need to pass */);
});

try {
  return requestWrapper.get(5000, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
  requestWrapper.cancel(true);
  throw new TimeoutException("Endpoint took too long to respond, TimeoutException is triggered");
} catch (ExecutionException e) {
  throw e.getCause();
}