[현상]
새로 지급 받은 리눅스 신규 장비에 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"
[원인]
해결 방법을 찾긴 했는데 왜 위의 옵션을 추가하면 지연 없이 톰켓이 구동되는지 찾아보았다.
리눅스 서버는 난수를 생성하기 위해서 기본적으로 /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 디바이스에 신호를 지속적으로 전송해서 블로킹 문제를 해소한다.
'서버' 카테고리의 다른 글
Kubernetes 설치 (6) | 2017.01.12 |
---|---|
Docker 정리 (2) | 2017.01.04 |
리눅스 컨테이너 (LXC) (0) | 2017.01.04 |
MQTT (mosquitto broker 오픈소스) (0) | 2016.11.02 |
Nginx (0) | 2016.07.15 |
Apache worker 파일에 template 적용하기 (0) | 2016.01.22 |
tomcat7 소스 빌드 (0) | 2015.09.07 |
Tomcat Parallel deployment (0) | 2015.09.02 |