라떼군 이야기
Java 그리고 리눅스 환경에서 Random Number 생성 지연 이슈
Problem
Java
를 사용하고 리눅스 환경에서 Random Number
를 생성할 때 약 10초 이상의 지연이 발생했다.
SecureRandom
1을 사용하고 있었고, Random
을 필요로 하는 클래스에서 클래스가 생성될 때 랜덤 시드를 설정해주고 있었다.
참고로 윈도우 환경의 같은 코드에서는 문제가 없었다. 참고로 문제가 있었던 코드의 일부는 다음과 같다.
public Signature(String key) {
...
try {
random = SecureRandom.getInstance("SHA1PRNG");
byte[] seed = random.generateSeed(NONCE_BYTE_LENGTH);
random.setSeed(seed);
} catch (NoSuchAlgorithmException e) {
}
Security.addProvider(new BouncyCastleProvider());
}
Solution
-
Avoiding JVM Delays Caused by Random Number Generation
2 설명이 되있듯이 Java는 기본/dev/random
를 사용하고 있고 이것은 플랫폼(운영체제)에 의존성이 있는데, 시스템에 노이즈 신호를 기다려 그것을 랜덤 함수 결과를 생성하는데 이용하기 때문에 지연현상이 발생할 수 있다.$JAVA_HOME/jre/lib/security/java.security
를 수정해서/dev/urandom
으로 변경하면 결과를 빠르게 얻을 수 있지만/dev/random
이 더 안전한 방식이다. -
또는, 1의 방법을 톰캣 실행시 옵션을 추가해서 수정할 수도 있다.3
-
이번 경우에는 1,2를 수정해줘도 해결되지 않았는데 코드에도 문제가 있었기 때문이었다.
SecureRandom
를 초기화하고seed
를 설정하는 부분을 아래와같이 초기화 시 한번만 실행되도록 변경하는 것으로 해결했다.4
try {
if (random == null) { // random is static variable
random = SecureRandom.getInstance("SHA1PRNG");
byte[] seed = random.generateSeed(NONCE_BYTE_LENGTH);
random.setSeed(seed);
}
} catch (NoSuchAlgorithmException e) {
}
- 그리고 추가로
Security Provider
를 설정하는 부분도 중복해서 처리되지 않도록 변경해 주었다.
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(new BouncyCastleProvider());
}