tomcat 구동 시 /dev/random 블로킹 이슈


[현상]
새로 지급 받은 리눅스 신규 장비에 java, tomcat 환경 구성을 하고 tomcat 구동 시 대기 상태로 빠지는 현상이 있었다. 특이한 점은 몇 분 지나면 tomcat 구동이 완료되는 경우와 몇 십 분이 지나도 서버 구동이 완료되지 않는 경우가 있다라는 것이다.

지연 현상이 발생되면서 다음과 같은 로그가 남았고, 해당 로그를 통해서 그 원인 및 해결 방법을 찾아보왔다.
[2016-08-23 18:10:36 INFO  o.s.w.c.ContextLoader][313] - Root WebApplicationContext: initialization completed in 2785 ms
8월 23, 2016 6:11:14 오후 org.apache.catalina.util.SessionIdGenerator createSecureRandom
INFO: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [38,251] milliseconds.



[해결방법]
해결 방법은 생각보다 쉽게 찾을 수 있었다. 다음의 java 옵션을 추가해 주면 tomcat 구동 시 더이상의 대기 상태는 발생하지 않았다.
JAVA_OPTS="$JAVA_OPTS -Djava.security.egd=file:/dev/./urandom"

232라인 catalina.sh



[원인]
해결 방법을 찾긴 했는데 왜 위의 옵션을 추가하면 지연 없이 톰켓이 구동되는지 찾아보았다.

리눅스 서버는 난수를 생성하기 위해서 기본적으로 /dev/random 디바이스를 사용한다.
 - 리눅스의 /dev 디렉토리는 시스템 디바이스 파일을 저장하고 있는 디렉토리이다.
   > 하드디스크는 /dev/sda
   > 씨디롬은 /dev/cdrom

/dev/random은 랜덤 비트의 풀이며 Entropy pool 이라고 부른다.
사용자 입력 신호(키보드, disk I/O, 마우스 click등)가 Entropy pool에 비트의 형태로 저장이 되고  난수를 생성할 때 Entropy pool에 default size만큼의 bit가 충분하지 않다면 /dev/random은 블로킹 된다.

여기서 /dev/random 이야기를 하는 이유는 자바에서 SecureRandom 클래스가 session ID를 생성할 때 /dev/random을 사용하기 때문이다. (위의 로그에 기록되어 있는 것 처럼 Creation of SecureRandom instance for session ID generation using [SHA1PRNG] 을 보면 알 수 있다.)

문제의 원인이 /dev/random 블로킹 상태로 빠지는 경우이기에 대체적으로 블로킹 되지 않는 /dev/urandom을 사용하도록 솔루션을 제공하고 있다.

여기서 한번 짚고 넘어가야 할 것은 왜 우리가 추가한 설정이 /dev/urandom이 아닌 /dev/./urandom 일까? 이것은 Java Bug 6202721 로 인한 영향도로 확인했다.
Java 5 또는 그 이후 버전에서는 /dev/./urandom 설정으로 추가해야 한다. 만약 /dev/urandom을 추가하게 되면 /dev/random으로 인식하게 되어 또 다시 블로킹 이슈가 발생할 수 있다.
Footnote: In the above examples, you need the crazy-looking filename, e.g., the extra /./, to trick Java into accepting your filename. If you just use /dev/urandom, Java decides you didn't really mean it and replaces what you wrote with /dev/random. Craziness!



[결론]
현재 /dev/random을 사용하고 있는 테스트, 라이브 장비에서는 블로킹 문제가 발생되고 있지 않은 상황이다.
이는 빈번한 I/O가 발생됨으로써 Entropy pool에 비트가 충분히 채워지고 있기 때문인 것으로 확인된다.
정상적으로 잘 동작하고 있는 환경의 톰켓에 굳이 urandom으로 설정을 바꿀 필요는 없을 것으로 보이며 위와 같은 블로킹 이슈가 발생되는 환경(개발망)에 대해서만 옵션을 추가하여 문제를 해결하는 것이 좋을 것 같다.

추가적으로 글을 쓰기 위해 이것 저것 조사하다 보니 rngd 데몬 프로그램을 이용해서 /dev/random의 블로킹 이슈를 해결하는 방법도 알게 되었다.
 - rngd 데몬 프로그램은 /dev/random 디바이스에 신호를 지속적으로 전송해서 블로킹 문제를 해소한다.

댓글

이 블로그의 인기 게시물

리눅스 시스템 시작시에 자동 실행할 파일 등록하기

Spring - MyBatis 연동 방법