问题描述

线上环境中很容易出现一个java应用启动非常耗时的情况,在日志中可以发现是session引起的随机数问题导致的

  1. o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [170,241] milliseconds.

分析

在Springboot程序中有内置的tomcat,在tomcat给的优化文档中,有一项是关于随机数生成时,采用的“熵源”(entropy source)的策略。

他提到tomcat7的session id的生成主要通过java.security.SecureRandom生成随机数来实现,随机数算法使用的是”SHA1PRNG”

  1. private String secureRandomAlgorithm = "SHA1PRNG";

在sun/oracle的jdk里,这个算法的提供者在底层依赖到操作系统提供的随机数据,在linux上,与之相关的是/dev/random和/dev/urandom。区别为:

/dev/random是阻塞的发生器

在读取时,/dev/random设备会返回小于熵池噪声总数的随机字节。/dev/random可生成高随机性的公钥或一次性密码本。若熵池空了,对/dev/random的读操作将会被阻塞,直到收集到了足够的环境噪声为止

而 /dev/urandom 则是一个非阻塞的发生器:

dev/random的一个副本是/dev/urandom (”unlocked”,非阻塞的随机数发生器),它会重复使用熵池中的数据以产生伪随机数据。这表示对/dev/urandom的读取操作不会产生阻塞,但其输出的熵可能小于/dev/random的。它可以作为生成较低强度密码的伪随机数生成器,不建议用于生成高强度长期密码。

这也并不是说明/dev/urandom不是做高强度的伪随机数生成器,这个讨论可以看这个讨论:/dev/urandom 不得不说的故事

解决方法

方法一

jre/lib/security/java.security 这个文件里面把

securerandom.source=file:/dev/random

改为

securerandom.source=file:/dev/./urandom

方法二

在启动参数中添加以下系统属性

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

这个系统属性egd表示熵收集守护进程(entropy gathering daemon),但这里值为何要在dev和random之间加一个点呢?是因为一个jdk的bug,在这个bug的连接里有人反馈及时对 securerandom.source 设置为 /dev/urandom 它也仍然使用的 /dev/random,有人提供了变通的解决方法,其中一个变通的做法是对securerandom.source设置为 /dev/./urandom 才行

多说一嘴

在Docker中如何添加系统参数呢

首先在build镜像时 要使用ENTRYPOINT 举个例子

  1. FROM jdk:alpine-security8
  2. WORKDIR /
  3. #解决中文乱码问题
  4. ENV LANG en_US.UTF-8
  5. ENV LANGUAGE en_US:en
  6. ENV LC_ALL en_US.UTF-8
  7. ADD sms-server.jar sms-server.jar
  8. ADD application.properties application.properties
  9. ADD bootstrap.properties bootstrap.properties
  10. ENV TZ=Asia/Shanghai
  11. RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
  12. ##使用如下的命令 添加-e JAVA_OPT是不起作用的
  13. #ENTRYPOINT ["java","-jar","sms-server.jar"]
  14. ##要使用这条命令才行
  15. ENTRYPOINT java ${JAVA_OPTS} -jar sms-server.jar

然后在启动命令中添加对应的-e参数就可以了 举个例子

  1. docker run --name sms-server-security \
  2. ## 如下即可
  3. -e JAVA_OPTS='-Djava.security.egd=file:/dev/./urandom' \
  4. -e spring.cloud.nacos.discovery.server-addr=192.169.1.82:8848 \
  5. -e spring.cloud.nacos.config.server-addr=192.169.1.82:8848 \
  6. -e spring.cloud.nacos.config.ext-config[0].data-id=sms-server-node1.properties \
  7. -p 8070:8090 \
  8. -v /opt/sms_server/log:/log \
  9. -v /opt/sms_server/nacos:/root/nacos \
  10. -d \
  11. 3a1c93c34756

参考

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

Springboot程序启动慢及JVM上的随机数与熵池策略的更多相关文章

  1. CentOS7 Tomcat 启动过程很慢,JVM上的随机数与熵池策略

    1. CentOS7 Tomcat 启动过程很慢 在centos启动官方的tomcat时,启动过程很慢,需要几分钟,经过查看日志,发现耗时在这里:是session引起的随机数问题导致的: <co ...

  2. JVM上的随机数与熵池策略

    在apache-tomcat官方文档:如何让tomcat启动更快里面提到了一些启动时的优化项,其中一项是关于随机数生成时,采用的“熵源”(entropy source)的策略. 他提到tomcat7的 ...

  3. SpringBoot程序启动时执行初始化代码

    因项目集成了Redis缓存部分数据,需要在程序启动时将数据加载到Redis中,即初始化数据到Redis. 在SpringBoot项目下,即在容器初始化完毕后执行我们自己的初始化代码. 第一步:创建实现 ...

  4. SpringBoot程序启动时在Oracle数据库中建表充值

    例子工程下载链接:https://files.cnblogs.com/files/xiandedanteng/gatling20200428-1.zip 需求:在工程启动时在Oracle数据库中建表. ...

  5. 深入理解SpringBoot之启动探究

    SpringApplication是SpringBoot的启动程序,我们通过它的run方法可以快速启动一个SpringBoot应用.可是这里面到底发生了什么?它是处于什么样的机制简化我们程序启动的?接 ...

  6. spring boot 程序启动缓慢的问题(二)

    今天发现一台服务器上的springboot程序启动特别慢,完全启动起来用了有好几分钟.刚开始以为是代码写的有问题造成了卡死,直到看到这条log: 2017-03-08 10:06:49.600 INF ...

  7. JVM内存模型以及HotSpot的GC策略

    概述 想要进一步掌握Java语言,必须要深入了解一下Java程序的运行环境.本文会对JVM的内存模型.Java内存自动管理机制.以及Oracle官方虚拟机HotSpot在GC方面的实现策略进行大概的梳 ...

  8. 痞子衡嵌入式:揭秘i.MXRT1060,1010上串行NOR Flash冗余程序启动设计

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1060,1010上串行NOR Flash冗余程序启动设计. 工业产品设计里经常会有冗余程序/备份程序设计的需求,因为在工业 ...

  9. 【Linux】【自学笔记】docker搭建一个spring-boot程序

    写在开始    最近捣腾Linux,安装虚拟机VMware并安装了CentOS 7系统,开始研究Linux,但是无从下手,就结合工作中用到的东西一步一步研究,事实并不是那么顺利.特此开博客,记录在过程 ...

随机推荐

  1. 蓝桥杯——分组比赛(2017JavaB组第3题)

    分组比赛(17JavaB3) 9名运动员参加比赛,需要分3组进行预赛. 有哪些分组的方案呢? 标记运动员为 A,B,C,... I 下面的程序列出了所有的分组方法: ABC DEF GHI ABC D ...

  2. 16个非常有趣的HTML5 Canvas动画特效集合

    HTML5技术正在不断的发展和更新,越来越多的开发者也正在加入HTML5阵营,甚至在移动开发上HTML5的地位也是越来越重要了.HTML5中的大部分动画都是通过Canvas实现,因为Canvas就像一 ...

  3. 记一次腾讯TBS浏览服务集成实践

    这次的分享源于最近的实际开发工作. 项目需求是 在原生Android应用中嵌入WebView,放置用于支撑音视频直播业务的Web页: 另外还需提供Word.Excel.PowerPoint.PDF等常 ...

  4. 【服务总线 Azure Service Bus】Service Bus在使用预提取(prefetching)后出现Microsoft.Azure.ServiceBus.MessageLockLostException异常问题

    问题描述 Service Bus接收端的日志中出现大量的MessageLockLostException异常.完整的错误消息为: Microsoft.Azure.ServiceBus.MessageL ...

  5. 05_Content Provider

    Content Provider是内容提供器,与内容(数据)的存取(存储.获取)有关,是Android应用程序的四大组成部分之一,是Android中的跨应用访问数据机制. 数据库在Android当中是 ...

  6. TensorFlow安装方法:附带坑解决办法

    >>添加Anaconda 仓库的镜像 Anaconda 安装包可以到 https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 下载. ...

  7. Error:Execution failed for task ':app:compileDebugAidl'. > java.lang.IllegalStateException: aidl is missing from '/Users/renguodong/Library/Android/sdk/build-tools/26.0.2/aidl'

    错误信息:Error:Execution failed for task ':app:compileDebugAidl'. > java.lang.IllegalStateException: ...

  8. 学习笔记(1):零基础掌握 Python 入门到实战-列表与元祖到底该用哪个?(二)...

    立即学习:https://edu.csdn.net/course/play/26676/338778?utm_source=blogtoedu 列表不能通过增加索引增加元素 可以使用list中的app ...

  9. 【原创】Linux虚拟化KVM-Qemu分析(七)之timer虚拟化

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...

  10. PyQt学习随笔:ListView控件增加列表项

    ListView控件如果需要增加列表项,就是在对应数据存储中插入项,这又分两种情况,一种是已知列表数据存储,一种是未知数据存储.如果是未知数据存储,可以通过: ListView控件名.model() ...