• Tomcat 生成 Session 堵塞引发的思考


    事故现象:

        public void handle(HttpServletRequest request, HttpServletResponse response) {
            //运行到此处的时候会阻塞,然后查看日志就爆出了如下日志  Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [14,387] milliseconds.
            if (request.getSession().getAttribute(WebConstants.SESSION.SESSION_USER_INFO) != null) {
                //...
            }
            //...
        }

    原因是  getSession() 时候 需要生成 SessionId,在生成Id的时候需要生成随机数,此时由于采用生成随机数的策略(file:/dev/random)是堵塞的,所以会堵塞很久,解决方案是采用非堵塞(file:/dev/urandom)方式生成随机数。

    好了,现在就出现了网上大多数的解决方式,启动参数添加如下参数,具体的原因可参考最下面几个连接

    -Djava.security.egd=file:/dev/./urandom

    但是,重点来了,如果你的JDK版本是 JDK8,其实启动参数添加以下即可,上下的区别在于多了一个 “./”(PS:其实在JDK8中 添加了 “./” 也能避免堵塞,但是是以另一种方式避免的,这个在文章最后会提到)

    -Djava.security.egd=file:/dev/urandom

    为何在JDK8 中 不需要添加 “./” ?

    请看  SeedGenerator.java 代码,只要你设置了  java.security.egd ,那么就会使用你所指定的生成器,而 JDK7 则不同,请继续往下看

    JDK7的代码如下

    如果 java.security.egd 参数指定的是 file:/dev/random 或者 file:/dev/urandom,则调用了无参的NativeSeedGenerator构造函数,而无参的构造函数将默认使用 file:/dev/random ,所以在JDK7中如果想要使用 file:/dev/urandom  就必须绕开第一个 if 判断,而使用 file:/dev/./urandom ,这样子才能使用你自定义的生成器

    那么,问题又来了,为什么在JDK8中使用 -Djava.security.egd=file:/dev/./urandom 也能解决堵塞的问题呢?

     所以,虽然 JDK8 使用 -Djava.security.egd=file:/dev/./urandom 也能达到相同的效果,但是它并不是使用我们给它解决方案来解决问题的

    附录:

    以下是 getSession()  生成随机数的关键断点处,有兴趣的话,可以动手断点运行一下

     

    参考:

    https://blog.csdn.net/u011687186/article/details/73224733

    http://hongjiang.info/jvm-random-and-entropy-source/

    http://hongjiang.info/java8-nativeprng-blocking/

    https://blog.51cto.com/leo01/1795447

  • 相关阅读:
    刷题力扣面试题 16.01. 交换数字
    git branch 分支操作
    数组的应用 创建的语法
    地址的替换,替换
    数组的扩容
    数组参数
    minio服务在linux安装部署 单机
    android studio出现 Could not initialize class com.android.sdklib.repository.AndroidSdkHandler
    Wireshark分割、合并pcap文件
    elasticsearch 删除index
  • 原文地址:https://www.cnblogs.com/fqybzhangji/p/12201885.html
Copyright © 2020-2023  润新知