Как увеличить время ожидания класса AsyncRestTemplate?

Я разработал несколько асинхронных веб-сервисов с помощью Spring Framework и REST, я использовал их от клиента, созданного с помощью Spring класса AsyncRestTemplate. Класс возвращает объект ListenableFuture<ResponseEntity<T>> (методом getForEntity), который возвращает значение, возвращаемое веб-службой (методом .get():<T>). Он работает нормально, однако, когда веб-службе требуется много времени, метод isDone() класса ListenableFuture возвращает значение true, даже если веб-служба еще не закончила работу.

Если я пытаюсь восстановить ответ веб-службы с помощью метода get() в клиенте, и он задерживается на много времени, я всегда получаю следующее сообщение:

   "timestamp": "2018-05-29T22:42:26.978+0000",
   "status": 500,
   "error": "Internal Server Error",
   "message": "java.util.concurrent.ExecutionException: org.springframework.web.client.HttpServerErrorException: 503 null",
   "path": "/client/result"

Кто-нибудь знает, как я могу решить проблему? Я хочу, чтобы клиент показывал мне ответ веб-службы, даже когда веб-служба занимает много времени (я хочу увеличить время ожидания).

Коды серверов следующие:

Класс конфигурации:

@Configuration
@EnableAsync
public class ConfigurationClass {
    @Bean
    public Executor threadPoolTaskExecutor() {
        return new ThreadPoolTaskExecutor();
    }
}

Класс контроллера:

@RestController
@RequestMapping("/server")
public class ControllerClass {

    @GetMapping("/start")
    @Async
    public CompletableFuture<String>  callService() throws InterruptedException{
        Thread.sleep(100000L);
        return CompletableFuture.completedFuture("OK");
    }
}

Код клиента (потребителя) следующий:

@RestController
@RequestMapping("/client")
public class ControllerClass {

    private ListenableFuture<ResponseEntity<String>> entity;

    @GetMapping("/start")
    @Async
    public void callService() throws InterruptedException {
        AsyncRestTemplate restTemplate = new AsyncRestTemplate();
        entity = restTemplate.getForEntity("http://localhost:8080/server/start",
                 String.class);
    }

    @GetMapping("/state")
    public boolean getState() {
        try {
            return entity.isDone();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @GetMapping("/result")
    public ResponseEntity<String> getResult() {
        try {
            return entity.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

Я попытался увеличить время ожидания свойства в файле application.property, но это не сработало.

# SPRING MVC (WebMvcProperties)
spring.mvc.async.request-timeout= 500000 # Amount of time before asynchronous request handling times out.

Спасибо за вашу помощь, С уважением.


person J. Abel    schedule 29.05.2018    source источник


Ответы (1)


Для лучшего обслуживания вы можете настроить bean-компонент AsyncRestTemplate:

@Bean
public AsyncRestTemplate asyncRestTemplate() {
    SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
    factory.setTaskExecutor(new SimpleAsyncTaskExecutor());
    factory.setConnectTimeout(1000);//milliseconds
    factory.setReadTimeout(2000);//milliseconds
    return new AsyncRestTemplate(factory);
}

А затем автоматически подключил этот компонент:

@Autowired
private AsyncRestTemplate restTemplate;

После этого обновите callService:

@GetMapping("/start")
public void callService() throws InterruptedException {
    entity = restTemplate.getForEntity("http://localhost:8080/server/start",
             String.class);
}

Вы можете удалить аннотацию @Async, так как AsyncRestTemplate является асинхронным.

person Chao Jiang    schedule 30.01.2019