2017-12-13 22 views
0

간단히 말해서 ServletContextListener은 tomcat이 시작될 때 프로세스를 실행하고, tomcat이 종료 될 때 프로세스를 종료합니다.tomcat7에 의해 생성 된 프로세스가 일시 중지됩니다.

프로세스 :

java -jar application.war -S rake jobs:work 

이 큐를 처리하는 루비 delayed_job 노동자를 생성합니다. 그러나 문제는 처리 할 일이 많거나 작업이 오래 걸릴 때 발생합니다. 그것은 몇 가지를 처리하고 그것은 단지 멈 춥니 다. 오류는 발생하지 않으며 로그에는 아무 것도 표시되지 않습니다. 그것은 단지 실행을 멈춘다.

서버를 다시 시작하면 종료 신호가 전송 된 로그에 항목이 입력됩니다. 작업자가 깨어나고 작업을 마치고 (실행 중에 일시 중지 된 경우) 작업을 종료합니다.

tomcat7 외부에서 해당 명령을 실행할 때 예상대로 작동합니다.

ServletContextListener 코드 :

public class RakeServlet implements ServletContextListener 
{ 
    private Process workerProcess; 

    @Override 
    public void contextInitialized(ServletContextEvent event) 
    { 
    workerProcess = Runtime.getRuntime().exec("java -jar application.war -S rake jobs:work"); 
    } 

    @Override 
    public void contextDestroyed(ServletContextEvent event) 
    { 
    workerProcess.destroy(); 
    } 
} 

ps aux 출력 :

tomcat7 2119 0.5 16.9 3479300 668704 ?  Sl 02:20 2:41 java -jar application.war -S rake jobs:wor 
+0

tomcat 대신 명령 줄에서 실행하면 처리가 중지되면 콘솔에 무엇이 출력됩니까? – Sam

+0

@Sam 명령 줄에서 실행하면 처리가 중지되지 않습니다. – Ruslan

+0

죄송합니다. 더 자세히 읽어야합니다. 입력을 쓰거나 응용 프로그램에서 사용하는 출력 스트림을 읽어야 할 수도 있습니다. 그렇게하지 않으면 응답이 중단 될 수 있습니다. Tomcat을 사용하여 war 파일을 직접로드하고 런타임 호출을 피할 수 있습니까? – Sam

답변

0

문제는 외부 프로세스를 실행할 때 자식 프로세스에서 stdoutstderr 스트림을 모두 읽을 수 있어야한다는 것입니다. 그렇지 않으면, 출력 버퍼가 가득 차면 프로세스는 효과적으로 I/O 쓰기 블록에서 일시 중지됩니다.

이 작업을 제대로 수행하려면 스트림을 모니터링하고 비우기 위해 일부 스레드를 시작해야합니다 (아마도 출력과 함께 유용하게 사용하고 단순히 폐기하지 말아야 할 것 같습니다).

자세한 내용은 Steve Liles's blog post on the subject에서 해결책에 대한 문제와 예제를 설명합니다.

대상 프로세스가 실제로 다른 Java 프로세스 인 경우 두 번째 JVM을 시작하는 오버 헤드와이 프로세스와 통신하는 복잡성 (즉 stdio 스트림)을 피하기 위해 Java 코드를 프로세스 내에서 실행하는 것을 고려해야합니다.

+0

해당 프로세스를 모두 분리 할 수 ​​있습니까? – Ruslan

+0

@Ruslan 쉘에서 프로세스를 "backgrounding"하는 것과 비슷한 의미입니까? 아니, Java에서 그걸 할 수있는 방법이 있다고 나는 믿지 않는다. 스트림 버퍼는 항상 문제가됩니다. Java에서 이러한 스트림을 다시 매핑하는 방법이 없습니다. 이미 열려있는 네이티브 파일 디스크립터. –