In our production environment, Tomcat starts very slow, we found this line below in tomcat’s log:
[2019-05-17 14:06:20] [localhost-startStop-1] INFO oacutil.SessionIdGenerator [T :] Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [213,586] milliseconds.
we did some google and found out The Java’s SecureRandom is reading operating system’s /dev/random synchronously .
(specifically is reading the configuration located at JAVA_HOME/jre/lib/security/java.security . In that file, it has a securerandom.source=file:/dev/random configuration item)
the value in the entropy pool is not enough, so it hangs in reading /dev/random which causing the slow startup
According to the official document of tomcat add following param
when jvm starts.
Or you can change the configuration securerandom.source in JAVA_HOME/jre/lib/security/java.security to securerandom.source=file:/dev/./urandom
choose one of the above methods will solve the problem.
The solution showing above is not very straight forward. Why is it written as file:/dev/./urandom instead of file:/dev/urandom? when changed to file:/dev/urandom, the jvm still read file:/dev/random.
I found this is a bug in jvm .
If java.security.egd or securerandom.source point to “file:/dev/random” or “file:/dev/urandom”, we will use NativeSeedGenerator, which calls super() which calls SeedGenerator.URLSeedGenerator(/dev/random).
(A nested class within SeedGenerator.) The only things that changed in this bug was that urandom will also trigger use of this code path.
so people use this NOT WELL DOCUMENTED workaround with file:/dev/./urandom .
But this problem does not exist in the development environment. Why does it exist in production environment?
our development environment is centOS while online environment is debian, direct cat /dev/random can find that the development environment can display several screens of random numbers immediately, while the online environment has less than 20 characters. In the page of “/dev/random” in wikipedia:/dev/random.
Here is a section in the page:
When the entropy pool is empty, reads from /dev/random will block until additional environmental noise is gathered. The intent is to serve as a cryptographically secure pseudorandom number generator, delivering output with entropy as large as possible. This is suggested by the authors for use in generating cryptographic keys for high-value or long-term protection.
A counterpart to /dev/random is /dev/urandom (“unlimited”/non-blocking random source) which reuses the internal pool to produce more pseudo-random bits. This means that the call will not block, but the output may contain less entropy than the corresponding read from /dev/random. While /dev/urandom is still intended as a pseudorandom number generator suitable for most cryptographic purposes, the authors of the corresponding man page note that, theoretically, there may exist an as-yet-unpublished attack on the algorithm used by /dev/urandom, and that users concerned about such an attack should use /dev/random instead. However such an attack is unlikely to come into existence, because once the entropy pool is unpredictable it doesn’t leak security by a reduced number of bits.