복붙노트

[SPRING] Spring을 멈춘다 일정 시간이 지나면 멈춘다.

SPRING

Spring을 멈춘다 일정 시간이 지나면 멈춘다.

Spring Framework의 Scheduled를 사용하여 cron을 사용하여 매 5 분마다 작업을 실행하도록 예약했습니다. 그러나 언젠가 내 직업은 외부 자원을 무한정 기다리고 거기에 시간 제한을 두지 못합니다. 이전 프로세스가 언젠가 대기 모드로 들어가고 매 5 분마다 데이터를 새로 고쳐야하기 때문에 fixedDelay를 사용할 수 없습니다.

그래서 나는 Spring Framework의 Scheduled에서 어떤 프로세스를 멈추게 할 것인가? 일정 시간이 지나면 프로세스가 성공적으로 실행될 것인가?

@Configuration 클래스에 넣은 keepAliveTime에 대해 120 초로 ThreadPoolExecutor를 초기화 한 설정을 아래에서 확인했습니다. 아무도 내가 예상했던대로이 작품을 말할 수 있습니까?

@Bean(destroyMethod="shutdown")
public Executor taskExecutor() {
    int coreThreads = 8;
    int maxThreads = 20;
    final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            coreThreads, maxThreads, 120L, 
            TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()
    );
    threadPoolExecutor.allowCoreThreadTimeOut(true);

    return threadPoolExecutor;
}

해결법

  1. ==============================

    1.이것이 예상대로 작동 할 지 확신하지 못합니다. 사실 keepAlive는 IDLE 스레드를위한 것이고 리소스를 기다리고있는 스레드가 유휴 상태인지 여부를 알지 못합니다. 또한 스레드 수가 코어보다 큰 경우에만 스레드 풀을 모니터링하지 않으면 실제로 발생하는시기를 알 수 없습니다.

    이것이 예상대로 작동 할 지 확신하지 못합니다. 사실 keepAlive는 IDLE 스레드를위한 것이고 리소스를 기다리고있는 스레드가 유휴 상태인지 여부를 알지 못합니다. 또한 스레드 수가 코어보다 큰 경우에만 스레드 풀을 모니터링하지 않으면 실제로 발생하는시기를 알 수 없습니다.

    할 수있는 일은 다음과 같습니다.

    public class MyTask {
    
        private final long timeout;
    
        public MyTask(long timeout) {
            this.timeout = timeout;
        }
    
        @Scheduled(cron = "")
        public void cronTask() {
            Future<Object> result = doSomething();
            result.get(timeout, TimeUnit.MILLISECONDS);
        }
    
        @Async
        Future<Object> doSomething() {
            //what i should do
            //get ressources etc...
        }
    }
    

    @EnableAsync를 추가하는 것을 잊지 마세요.

    Callable을 구현하여 @Async 없이도 동일한 작업을 수행 할 수 있습니다.

    편집 : 그것은 시간 초과까지 기다릴 것이지만 작업을 실행하는 스레드가 중단되지 않는다는 것을 명심하십시오. TimeoutException이 발생하면 Future.cancel을 호출해야합니다. 작업에서 isInterrupted ()이 처리를 중지하는지 확인합니다. API를 호출하는 경우 isInterrupted ()이 선택되어 있는지 확인하십시오.

  2. ==============================

    2.allowCoreThreadTimeOut 및 timeout 설정이 작동하지 않고 잠시 후에 작업 스레드가 종료되도록 허용하지 않습니다 (javadocs 참조).

    allowCoreThreadTimeOut 및 timeout 설정이 작동하지 않고 잠시 후에 작업 스레드가 종료되도록 허용하지 않습니다 (javadocs 참조).

    당신은 당신의 직업이 외부 자원을 무한정 기다리고 있다고 말합니다. 나는 당신이 (또는 당신이 사용하는 제 3 자 라이브러리가) 무한정으로 타임 아웃을하는 소켓을 사용하기 때문이라고 확신한다. 또한 jvm이 socket.connect / read에서 차단할 때 Thread.interrupt ()를 무시하는 것을 명심하십시오.

    그래서 마녀 소켓 라이브러리를 사용하여 작업에 사용되는 (그리고 정확히 사용되는 방법) 기본 시간 제한 설정을 변경하십시오.

    예를 들면, RestTemplate은 Spring 내부에서 널리 사용됩니다 (휴식 클라이언트, 봄철 사회, 봄 보안 OAuth 등). 그리고 RestTemplate 인스턴스를 생성하기위한 ClientHttpRequestFactory 구현이 있습니다. 기본적으로 스프링은 JDK 소켓을 사용하는 SimpleClientHttpRequestFactory를 사용합니다. 기본적으로 모든 시간 제한은 무한합니다.

    그래서 정확히 어디서 멈추고, 문서를 읽고 올바르게 구성하는지 확인하십시오.

    추신 시간이 충분하지 않고 "운이 좋았다"면 jvm 속성 sun.net.client.defaultConnectTimeout을 설정하여 응용 프로그램을 실행하십시오. sun.net.client.defaultReadTimeout을 적절한 값으로 변경하십시오 (자세한 내용은 docs를 참조하십시오).

  3. ==============================

    3.keepAliveTime은 잠시 동안 필요하지 않은 작업자 스레드를 제거하기위한 것일 뿐이며 실행 프로그램에 제출 된 작업의 실행 시간에는 영향을 미치지 않습니다.

    keepAliveTime은 잠시 동안 필요하지 않은 작업자 스레드를 제거하기위한 것일 뿐이며 실행 프로그램에 제출 된 작업의 실행 시간에는 영향을 미치지 않습니다.

    시간이 지남에 따라 인터럽트를 존중하면 새 스레드를 시작하고 타임 아웃에 참여하여 시간 내에 완료되지 않으면 인터럽트를 중단 할 수 있습니다.

    public class SomeService {
    
        @Scheduled(fixedRate = 5 * 60 * 1000)
        public void doSomething() throws InterruptedException {
            Thread taskThread = new TaskThread();
            taskThread.start();
            taskThread.join(120 * 000);
            if(taskThread.isAlive()) {
                // We timed out
                taskThread.interrupt();
            }
        }
    
        private class TaskThread extends Thread {
    
            public void run() {
                // Do the actual work here
            }
        }
    }
    
  4. from https://stackoverflow.com/questions/39917757/stop-spring-scheduled-execution-if-it-hangs-after-some-fixed-time by cc-by-sa and MIT license