服务响应时间慢:Java SecureRandom&/开发/随机
我试图调试部署在Tomcat上的应用程序提供的一些缓慢响应。 现在我主要关注的是服务响应时间慢:Java SecureRandom&/开发/随机,java,tomcat,random,aes,strace,Java,Tomcat,Random,Aes,Strace,我试图调试部署在Tomcat上的应用程序提供的一些缓慢响应。 现在我主要关注的是SecureRandom和/dev/random(其他一些可能的原因已经调查并排除)。 模式如下: 第一次调用在Tomcat重新启动后正好30.0xy秒(即使请求在启动后4分钟到达) 后来,有些通话只需15.0pq秒(我无法确定具体模式,pq是TP99中所用时间的近似值) 服务调用涉及加密和解密(AES/ECB/PKCS5P) SecureRandom初始化/重新填充是否可能导致这种情况 (尽管如此,catali
SecureRandom
和/dev/random
(其他一些可能的原因已经调查并排除)。
模式如下:
- 第一次调用在Tomcat重新启动后正好30.0xy秒(即使请求在启动后4分钟到达)
- 后来,有些通话只需15.0pq秒(我无法确定具体模式,pq是TP99中所用时间的近似值)
“使用[SHA1PRNG]为会话ID生成创建SecureRandom实例需要[28760]毫秒。”
)
另外,为了检查是否正在使用/dev/random
或/dev/uradom
,我使用了来自的测试。令我惊讶的是,我没有看到他们中的任何一个读到的内容,这与链接问题中的情况不同。
以下是strace
日志中的最后几行:
3561 lstat("/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/jsse.jar", {st_mode=S_IFREG|0644, st_size=258525, ...}) = 0
3561 open("/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/jsse.jar", O_RDONLY) = 6
3561 stat("/dev/random", {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 8), ...}) = 0
3561 stat("/dev/urandom", {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 9), ...}) = 0
3561 open("/dev/random", O_RDONLY) = 7
3561 open("/dev/urandom", O_RDONLY) = 8
3561 unlink("/tmp/hsperfdata_xxxx/3560") = 0
那么,什么是用来播种的呢
仅供参考,java版本
我无法检查您的OpenJDK具体版本,但我可以检查 用于获取种子字节
public byte[] engineGenerateSeed(int numBytes) {
byte[] b = new byte[numBytes];
SeedGenerator.generateSeed(b);
return b;
}
SeedGenerator从中获取seedSource
(字符串)
SunEntries
首先尝试从系统属性java.security.egd
获取源,如果未找到,则尝试从java.security
属性文件获取属性securerandom.source
,如果未找到属性,则返回空字符串
// name of the *System* property, takes precedence over PROP_RNDSOURCE
private final static String PROP_EGD = "java.security.egd";
// name of the *Security* property
private final static String PROP_RNDSOURCE = "securerandom.source";
final static String URL_DEV_RANDOM = "file:/dev/random";
final static String URL_DEV_URANDOM = "file:/dev/urandom";
private static final String seedSource;
static {
seedSource = AccessController.doPrivileged(
new PrivilegedAction<String>() {
public String run() {
String egdSource = System.getProperty(PROP_EGD, "");
if (egdSource.length() != 0) {
return egdSource;
}
egdSource = Security.getProperty(PROP_RNDSOURCE);
if (egdSource == null) {
return "";
}
return egdSource;
}
});
}
如果来源是
final static String URL_DEV_RANDOM = "file:/dev/random";
或
使用NativeSeedGenerator
,在Windows上尝试在Linux上使用本机CryptoAPI
,该类仅扩展SeedGenerator.URLSeedGenerator
package sun.security.provider;
import java.io.IOException;
/**
* Native seed generator for Unix systems. Inherit everything from
* URLSeedGenerator.
*
*/
class NativeSeedGenerator extends SeedGenerator.URLSeedGenerator {
NativeSeedGenerator() throws IOException {
super();
}
}
并调用默认情况下加载/dev/random
的超类构造函数
URLSeedGenerator() throws IOException {
this(SeedGenerator.URL_DEV_RANDOM);
}
因此,OpenJDK默认使用/dev/random
,直到您没有在系统属性java.security.egd
或安全属性文件的属性securerandom.source
中设置另一个值为止
如果要使用strace
查看读取结果,可以更改命令行并添加trace=open,read
表达式
sudo strace -o a.strace -f -e trace=open,read java class
您可以看到类似的内容(我使用OracleJDK6进行了测试)
更快启动的Tomcat Wiki部分建议,如果您在启动过程中遇到延迟,请使用非阻塞熵源,如/dev/uradom
更多信息:
希望这有帮助。问题不在于SecureRandom本身,而在于/dev/random如果没有足够的数据就会阻塞。您可以使用Uradom,但如果您需要加密的强随机种子,这可能不是一个好主意。 在无头Linux系统上,您可以安装haveged守护进程。这将为/dev/random添加足够的数据,以便调用不必等待生成所需的熵。
我在Debian Aws实例上做了这项工作,看到SecureRandom generateBytes调用从25秒下降到亚毫秒(Openjdk 1.7之类的,不记得具体是哪个版本) 您可以尝试一个小应用程序,创建一个新的随机生成器(使用
newsecurerandom
),然后从中读取一些字节,看看是否从urandom
读取。但是,请确保您的目标是相同的Java运行时,并检查是否未使用Tomcat的Java-D
设置Java.security.egd
属性。我确实运行了一个示例程序(代码取自链接上的问题)。它既不是从/dev/random读取的,也不是从/dev/random读取的,如问题所附的strace日志所示。您还可以检查jre/lib/security/java.security
并检查securerandom.source
是如何定义的吗?谢谢@owlstead。它是/dev/uradom。你能试试那里的/dev//uradom
看看会发生什么吗?感谢读取的跟踪,我确认\dev\uradom
正在这个JVM中使用。没有egd覆盖和securerandom.source也是\dev\uradom
。所以,这排除了SecureRandom作为原因的可能性,我将不得不研究其他可能的原因。
final static String URL_DEV_URANDOM = "file:/dev/urandom"
package sun.security.provider;
import java.io.IOException;
/**
* Native seed generator for Unix systems. Inherit everything from
* URLSeedGenerator.
*
*/
class NativeSeedGenerator extends SeedGenerator.URLSeedGenerator {
NativeSeedGenerator() throws IOException {
super();
}
}
URLSeedGenerator() throws IOException {
this(SeedGenerator.URL_DEV_RANDOM);
}
sudo strace -o a.strace -f -e trace=open,read java class
13225 open("/dev/random", O_RDONLY) = 8
13225 read(8, "@", 1) = 1
13225 read(3, "PK\3\4\n\0\0\0\0\0RyzB\36\320\267\325u\4\0\0u\4\0\0 \0\0\0", 30) = 30
....
....