#java #spring-boot #spring-mvc
#java #spring-boot #spring-mvc
Вопрос:
Я разрабатываю приложение spring boot, в котором есть бизнес-требование, в соответствии с которым я должен продолжать вызывать внешний API, пока не получу Http status 204 No Content от этого. Однако этот процесс занимает очень много времени, поэтому я использую отложенный результат в своем методе контроллера, чтобы я мог освободить поток сервера, но сохранить соединение с браузером. Но после попадания в конечную точку моего приложения я получаю это исключение в ответ через некоторое время
{
"timestamp": "2020-11-08T12:43:31.560 0000",
"status": 503,
"error": "Service Unavailable",
"message": "No message available",
"trace": "org.springframework.web.context.request.async.AsyncRequestTimeoutExceptionrntat org.springframework.web.context.request.async.TimeoutDeferredResultProcessingInterceptor.handleTimeout(TimeoutDeferredResultProcessingInterceptor.java:42)rntat org.springframework.web.context.request.async.DeferredResultInterceptorChain.triggerAfterTimeout(DeferredResultInterceptorChain.java:79)rntat org.springframework.web.context.request.async.WebAsyncManager.lambda$startDeferredResultProcessing$5(WebAsyncManager.java:424)rntat java.util.ArrayList.forEach(ArrayList.java:1249)rntat org.springframework.web.context.request.async.StandardServletAsyncWebRequest.onTimeout(StandardServletAsyncWebRequest.java:150)rntat org.apache.catalina.core.AsyncListenerWrapper.fireOnTimeout(AsyncListenerWrapper.java:44)rntat org.apache.catalina.core.AsyncContextImpl.timeout(AsyncContextImpl.java:133)rntat org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:153)rntat org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:241)rntat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53)rntat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)rntat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)rntat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)rntat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)rntat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)rntat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)rntat java.lang.Thread.run(Thread.java:745)rn",
"path": "/api/datasync"
}
но процесс вызова внешнего API и получения ответа продолжается даже после получения приведенного выше ответа об ошибке. Однако в server.log не регистрируется никаких исключений или ошибок
Вот моя функция контроллера
@GetMapping("/documentinfo/datasync")
public DeferredResult<ResponseEntity<String>> getData(@RequestParam(name = "update", required = false, defaultValue = "no") String manuallyInvoked) throws Exception {
log.info("Inside getData Method. Delegating request to Service Layer");
log.info("Manually invoked by user");
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>();
ForkJoinPool forkJoinPool = new ForkJoinPool();
forkJoinPool.submit(() -> {
log.info("Inside Pool");
result.setResult(new ResponseEntity<String>(dataImportService.getData(),HttpStatus.OK));
});
log.info("Finished Importing data");
return resu<
}
Здесь dataImportService.getData() — это мой метод сервисного уровня, который вызывает очередь и потребляет данные.
Комментарии:
1. Я думаю, вы предусмотрели некоторую задержку внутри выполнения метода. Это означает использование потока внутри этого метода. По моему мнению, проблема в том, что вы не даете достаточно времени для обработки этого метода.
2. @BawanthaWickramarachchi Нет, я ничего не добавил. Метод на уровне сервиса прост: он вызывает внешний API и сохраняет ответ
3. Да, это может быть проблемой. Чтобы вызвать внешний API, вам нужно дать на это некоторое время. Обратитесь к асинхронным методам в java. Это метод, используемый внутри такого рода методов.
4. Но даже после получения ответа об ошибке процесс продолжается, и он извлекает данные из внешнего API и сохраняет их в базе данных.
Ответ №1:
укажите spring.mvc.async.request-timeout
в application.yml
spring:
mvc:
async:
request-timeout: 30m