服务响应时间慢:Java SecureRandom& / dev /随机 [英] Slow service response Times : Java SecureRandom & /dev/random

查看:138
本文介绍了服务响应时间慢:Java SecureRandom& / dev /随机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试调试Tomcat上部署的应用程序提供的一些慢速响应。
现在,我主要关注 SecureRandom / dev / random (其他一些可能的原因有已被调查并排除)。
模式如下:

I am trying to debug a few slow responses served by an app deployed on Tomcat. Right now I am focussing on SecureRandom and /dev/random (some of the other probable causes have been investigated and ruled out). The pattern is as follows:


  • 在Tomcat重新启动后,第一次调用恰好在 30.0 xy秒内(即使请求在启动后4分钟到达)

  • 稍后,某些呼叫恰好需要 15.0 pq秒(我无法建立具体的模式, pq 是大约在TP99中花费的时间)

  • The first call takes exactly 30.0xy seconds after Tomcat restart (even if the request arrives 4 minutes after the Startup)
  • Later, some calls take exactly 15.0pq seconds (there was no specific pattern that I could establish, pq being the time approximate time taken in TP99)

服务调用涉及加密和解密( AES / ECB / PKCS5Padding )。

The service call involves encryption and decryption (AES/ECB/PKCS5Padding).

是否可能通过SecureRandom初始化/重新填充导致了此错误?

(尽管在catalina.log中写了一个日志,其中显示 使用[SHA1PRNG]创建用于生成会话ID的SecureRandom实例花费了[28,760]毫秒。 c

(Although, there is a log written in catalina.log that says "Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [28,760] milliseconds.")

此外,为了检查 / dev / random 还是正在使用 / dev / urandom ,我从这个问题。令我惊讶的是,与链接问题中发生的情况不同,我没有看到它们中的任何一个。
这是 strace 日志的最后几行:

Also, in order to check whether /dev/random or /dev/urandom is being used, I used the test from this question. To my surprise, I didn't see reads from either of them unlike the way it happens in the linked question. These are the last few lines from the strace log:

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

然后使用什么作为SecureRandom的种子?

What is then being used for seeding SecureRandom?

fyi, java -version

java version "1.6.0_32"
OpenJDK Runtime Environment (IcedTea6 1.13.4) (rhel-7.1.13.4.el6_5-x86_64)
OpenJDK 64-Bit Server VM (build 23.25-b01, mixed mode)


推荐答案

我无法检查您的OpenJDK具体版本,但可以检查 jdk6-b33

I could not check your OpenJDK concrete version, but I could check jdk6-b33.

SecureRandom 使用 SeedGenerator 获取种子字节

public byte[] engineGenerateSeed(int numBytes) {
    byte[] b = new byte[numBytes];
    SeedGenerator.generateSeed(b);
    return b;
}

SeedGenerator获取 seedSource (字符串)来自 SunEntries

SeedGenerator gets the seedSource (String) from SunEntries

String egdSource = SunEntries.getSeedSource();

SunEntries 试图从首先,找到系统属性 java.security.egd ,然后尝试从系统属性中获取属性 securerandom.source java.security 属性文件,如果找不到该属性,则返回空白字符串。

SunEntries tries to get the source from the system property java.security.egd first, if is not found then tries to get the property securerandom.source from the java.security properties file, if the property is not found returns a blank string.

// 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;
        }
    });
}

SeedGenerator 支票该值用于初始化实例

the SeedGenerator check this value to initialize the instance

// Static instance is created at link time
private static SeedGenerator instance;

private static final Debug debug = Debug.getInstance("provider");

final static String URL_DEV_RANDOM = SunEntries.URL_DEV_RANDOM;
final static String URL_DEV_URANDOM = SunEntries.URL_DEV_URANDOM;

// Static initializer to hook in selected or best performing generator
static {
    String egdSource = SunEntries.getSeedSource();

    // Try the URL specifying the source
    // e.g. file:/dev/random
    //
    // The URL file:/dev/random or file:/dev/urandom is used to indicate
    // the SeedGenerator using OS support, if available.
    // On Windows, the causes MS CryptoAPI to be used.
    // On Solaris and Linux, this is the identical to using
    // URLSeedGenerator to read from /dev/random

    if (egdSource.equals(URL_DEV_RANDOM) || egdSource.equals(URL_DEV_URANDOM)) {
        try {
            instance = new NativeSeedGenerator();
            if (debug != null) {
                debug.println("Using operating system seed generator");
            }
        } catch (IOException e) {
            if (debug != null) {
                debug.println("Failed to use operating system seed "
                              + "generator: " + e.toString());
            }
        }
    } else if (egdSource.length() != 0) {
        try {
            instance = new URLSeedGenerator(egdSource);
            if (debug != null) {
                debug.println("Using URL seed generator reading from "
                              + egdSource);
            }
        } catch (IOException e) {
            if (debug != null)
                debug.println("Failed to create seed generator with "
                              + egdSource + ": " + e.toString());
        }
    }

    // Fall back to ThreadedSeedGenerator
    if (instance == null) {
        if (debug != null) {
            debug.println("Using default threaded seed generator");
        }
        instance = new ThreadedSeedGenerator();
    }
}

如果来源是

final static String URL_DEV_RANDOM = "file:/dev/random";

final static String URL_DEV_URANDOM = "file:/dev/urandom"

使用<$ Windows上的c $ c> NativeSeedGenerator 尝试在Linux上使用本机 CryptoAPI ,该类只是扩展了 SeedGenerator.URLSeedGenerator

uses the NativeSeedGenerator, on Windows tries to use the native CryptoAPI on Linux the class simply extends the 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

and call to the superclass constructor who loads /dev/random by default

URLSeedGenerator() throws IOException {
    this(SeedGenerator.URL_DEV_RANDOM);
}

因此,OpenJDK使用 / dev / random ,直到您未在系统属性 java.security.egd 或属性 securerandom.source 安全属性文件。

so, OpenJDK uses /dev/random by default until you do not set another value in the system property java.security.egd or in the property securerandom.source of security properties file.

如果要使用 strace 查看读取结果,则可以更改命令行并添加 trace = open,read 表达式

If you want to see the read results using strace you can change the command line and add the trace=open,read expression

sudo strace -o a.strace -f -e trace=open,read java class

可以看到这样的内容(我使用Oracle JDK 6进行了测试)

the you can see something like this (I did the test with Oracle JDK 6)

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
....
....

Tomcat Wiki部分启动速度更快,建议使用非阻塞熵源,例如/ dev / u如果您在启动过程中遇到延迟,则为随机

The Tomcat Wiki section for faster startup suggest using a non-blocking entropy source like /dev/urandom if you are experiencing delays during startup

更多信息: https://wiki.apache.org/tomcat/HowTo/FasterStartUp#Entropy_Source

希望这会有所帮助。

这篇关于服务响应时间慢:Java SecureRandom&amp; / dev /随机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆