springboot项目执行controller方法时进入慢的问题
今天在部署springboot项目到阿里云时,出现登录方法执行特别慢的问题。刚开始以为是卡死了,等了3,4分钟才进去,最后会出现如下信息:
2018-01-28 15:38:36.958 INFO 4374 --- [p-nio-80-exec-1] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [329,771] milliseconds.
2018-01-28 15:38:36.976 INFO 4374 --- [p-nio-80-exec-9] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [45,744] milliseconds.
从提示信息看,是sessionID相关的生成器的提示。在搜索SessionIdGeneratorBase之后,发现是tomcat的session生成策略。完整代码如下:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.util;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.SessionIdGenerator;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;
public abstract class SessionIdGeneratorBase extends LifecycleBase
implements SessionIdGenerator {
private static final Log log = LogFactory.getLog(SessionIdGeneratorBase.class);
private static final StringManager sm =
StringManager.getManager("org.apache.catalina.util");
/**
* Queue of random number generator objects to be used when creating session
* identifiers. If the queue is empty when a random number generator is
* required, a new random number generator object is created. This is
* designed this way since random number generators use a sync to make them
* thread-safe and the sync makes using a a single object slow(er).
*/
private final Queue<SecureRandom> randoms = new ConcurrentLinkedQueue<>();
private String secureRandomClass = null;
private String secureRandomAlgorithm = "SHA1PRNG";
private String secureRandomProvider = null;
/** Node identifier when in a cluster. Defaults to the empty string. */
private String jvmRoute = "";
/** Number of bytes in a session ID. Defaults to 16. */
private int sessionIdLength = 16;
/**
* Get the class name of the {@link SecureRandom} implementation used to
* generate session IDs.
*
* @return The fully qualified class name. {@code null} indicates that the
* JRE provided {@link SecureRandom} implementation will be used
*/
public String getSecureRandomClass() {
return secureRandomClass;
}
/**
* Specify a non-default {@link SecureRandom} implementation to use. The
* implementation must be self-seeding and have a zero-argument constructor.
* If not specified, an instance of {@link SecureRandom} will be generated.
*
* @param secureRandomClass The fully-qualified class name
*/
public void setSecureRandomClass(String secureRandomClass) {
this.secureRandomClass = secureRandomClass;
}
/**
* Get the name of the algorithm used to create the {@link SecureRandom}
* instances which generate new session IDs.
*
* @return The name of the algorithm. {@code null} or the empty string means
* that platform default will be used
*/
public String getSecureRandomAlgorithm() {
return secureRandomAlgorithm;
}
/**
* Specify a non-default algorithm to use to create instances of
* {@link SecureRandom} which are used to generate session IDs. If no
* algorithm is specified, SHA1PRNG is used. To use the platform default
* (which may be SHA1PRNG), specify {@code null} or the empty string. If an
* invalid algorithm and/or provider is specified the {@link SecureRandom}
* instances will be created using the defaults for this
* {@link SessionIdGenerator} implementation. If that fails, the
* {@link SecureRandom} instances will be created using platform defaults.
*
* @param secureRandomAlgorithm The name of the algorithm
*/
public void setSecureRandomAlgorithm(String secureRandomAlgorithm) {
this.secureRandomAlgorithm = secureRandomAlgorithm;
}
/**
* Get the name of the provider used to create the {@link SecureRandom}
* instances which generate new session IDs.
*
* @return The name of the provider. {@code null} or the empty string means
* that platform default will be used
*/
public String getSecureRandomProvider() {
return secureRandomProvider;
}
/**
* Specify a non-default provider to use to create instances of
* {@link SecureRandom} which are used to generate session IDs. If no
* provider is specified, the platform default is used. To use the platform
* default specify {@code null} or the empty string. If an invalid algorithm
* and/or provider is specified the {@link SecureRandom} instances will be
* created using the defaults for this {@link SessionIdGenerator}
* implementation. If that fails, the {@link SecureRandom} instances will be
* created using platform defaults.
*
* @param secureRandomProvider The name of the provider
*/
public void setSecureRandomProvider(String secureRandomProvider) {
this.secureRandomProvider = secureRandomProvider;
}
/**
* Return the node identifier associated with this node which will be
* included in the generated session ID.
*/
@Override
public String getJvmRoute() {
return jvmRoute;
}
/**
* Specify the node identifier associated with this node which will be
* included in the generated session ID.
*
* @param jvmRoute The node identifier
*/
@Override
public void setJvmRoute(String jvmRoute) {
this.jvmRoute = jvmRoute;
}
/**
* Return the number of bytes for a session ID
*/
@Override
public int getSessionIdLength() {
return sessionIdLength;
}
/**
* Specify the number of bytes for a session ID
*
* @param sessionIdLength Number of bytes
*/
@Override
public void setSessionIdLength(int sessionIdLength) {
this.sessionIdLength = sessionIdLength;
}
/**
* Generate and return a new session identifier.
*/
@Override
public String generateSessionId() {
return generateSessionId(jvmRoute);
}
protected void getRandomBytes(byte bytes[]) {
SecureRandom random = randoms.poll();
if (random == null) {
random = createSecureRandom();
}
random.nextBytes(bytes);
randoms.add(random);
}
/**
* Create a new random number generator instance we should use for
* generating session identifiers.
*/
private SecureRandom createSecureRandom() {
SecureRandom result = null;
long t1 = System.currentTimeMillis();
if (secureRandomClass != null) {
try {
// Construct and seed a new random number generator
Class<?> clazz = Class.forName(secureRandomClass);
result = (SecureRandom) clazz.newInstance();
} catch (Exception e) {
log.error(sm.getString("sessionIdGeneratorBase.random",
secureRandomClass), e);
}
}
if (result == null) {
// No secureRandomClass or creation failed. Use SecureRandom.
try {
if (secureRandomProvider != null &&
secureRandomProvider.length() > 0) {
result = SecureRandom.getInstance(secureRandomAlgorithm,
secureRandomProvider);
} else if (secureRandomAlgorithm != null &&
secureRandomAlgorithm.length() > 0) {
result = SecureRandom.getInstance(secureRandomAlgorithm);
}
} catch (NoSuchAlgorithmException e) {
log.error(sm.getString("sessionIdGeneratorBase.randomAlgorithm",
secureRandomAlgorithm), e);
} catch (NoSuchProviderException e) {
log.error(sm.getString("sessionIdGeneratorBase.randomProvider",
secureRandomProvider), e);
}
}
if (result == null) {
// Invalid provider / algorithm
try {
result = SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
log.error(sm.getString("sessionIdGeneratorBase.randomAlgorithm",
secureRandomAlgorithm), e);
}
}
if (result == null) {
// Nothing works - use platform default
result = new SecureRandom();
}
// Force seeding to take place
result.nextInt();
long t2=System.currentTimeMillis();
if( (t2-t1) > 100 )
log.info(sm.getString("sessionIdGeneratorBase.createRandom",
result.getAlgorithm(), Long.valueOf(t2-t1)));
return result;
}
@Override
protected void initInternal() throws LifecycleException {
// NO-OP
}
@Override
protected void startInternal() throws LifecycleException {
// Ensure SecureRandom has been initialised
generateSessionId();
setState(LifecycleState.STARTING);
}
@Override
protected void stopInternal() throws LifecycleException {
setState(LifecycleState.STOPPING);
randoms.clear();
}
@Override
protectedvoiddestroyInternal()throws LifecycleException {
// NO-OP
}
}
其实tomcat官方也给出过类似问题的说明:
Tomcat 7+ heavily relies on SecureRandom class to provide random values for its session ids and in other places. Depending on your JRE it can cause delays during startup if entropy source that is used to initialize SecureRandom is short of entropy. You will see warning in the logs when this happens, e.g.:
<DATE> org.apache.catalina.util.SessionIdGenerator createSecureRandom
INFO: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [5172] milliseconds.
网上搜索之后,发现有类似的问题出现过,具体的解决办法如下: 找到安装的jre目录,如jre/lib/security,然后修改java.security文件的如下:
securerandom.source=file:/dev./urandom
要注意./不是/。另外,对于该属性,也有如下描述:
#
# Sun Provider SecureRandom seed source.
#
# Select the primary source of seed data for the "SHA1PRNG" and
# "NativePRNG" SecureRandom implementations in the "Sun" provider.
# (Other SecureRandom implementations might also use this property.)
#
# On Unix-like systems (for example, Solaris/Linux/MacOS), the
# "NativePRNG" and "SHA1PRNG" implementations obtains seed data from
# special device files such as file:/dev/random.
#
# On Windows systems, specifying the URLs "file:/dev/random" or
# "file:/dev/urandom" will enable the native Microsoft CryptoAPI seeding
# mechanism for SHA1PRNG.
#
# By default, an attempt is made to use the entropy gathering device
# specified by the "securerandom.source" Security property. If an
# exception occurs while accessing the specified URL:
#
# SHA1PRNG:
# the traditional system/thread activity algorithm will be used.
#
# NativePRNG:
# a default value of /dev/random will be used. If neither
# are available, the implementation will be disabled.
# "file" is the only currently supported protocol type.
#
# The entropy gathering device can also be specified with the System
# property "java.security.egd". For example:
#
# % java -Djava.security.egd=file:/dev/random MainClass
#
# Specifying this System property will override the
# "securerandom.source" Security property.
#
# In addition, if "file:/dev/random" or "file:/dev/urandom" is
# specified, the "NativePRNG" implementation will be more preferred than
# SHA1PRNG in the Sun provider.
然后,重新启动项目,发现秒进。 另外,网友也给出了在启动时指定参数的方式,如下:
-Djava.security.egd=file:/dev/./urandom
但我设置了没用,具体原因不明。
springboot项目执行controller方法时进入慢的问题的更多相关文章
- SpringBoot项目打成Jar包时运行
使用java -jar ***.jar执行jar包的时候,会找jar包中的main()方法. 对于SpringBoot项目的Jar包,在META-INF目录下的MANIFEST.MF文件中,Main- ...
- netty笔记-:Channel与ChannelHandlerContext执行write方法的区别
在netty中有我们一般有两种发送数据的方式,即使用ChannelHandlerContext或者Channel的write方法,这两种方法都能发送数据,那么其有什么区别呢.这儿引用netty文档 ...
- Mybatis:解决调用带有集合类型形参的mapper方法时,集合参数为空或null的问题
此文章有问题,待修改! 使用Mybatis时,有时需要批量增删改查,这时就要向mapper方法中传入集合类型(List或Set)参数,下面是一个示例. // 该文件不完整,只展现关键部分 @Mappe ...
- springboot 学习之路 9 (项目启动后就执行特定方法)
目录:[持续更新.....] spring 部分常用注解 spring boot 学习之路1(简单入门) spring boot 学习之路2(注解介绍) spring boot 学习之路3( 集成my ...
- C#编译器优化那点事 c# 如果一个对象的值为null,那么它调用扩展方法时为甚么不报错 webAPI 控制器(Controller)太多怎么办? .NET MVC项目设置包含Areas中的页面为默认启动页 (五)Net Core使用静态文件 学习ASP.NET Core Razor 编程系列八——并发处理
C#编译器优化那点事 使用C#编写程序,给最终用户的程序,是需要使用release配置的,而release配置和debug配置,有一个关键区别,就是release的编译器优化默认是启用的.优化代码 ...
- 在web项目启动时,使用监听器来执行某个方法
在web项目中有很多时候需要在项目启动时就执行一些方法,而且只需要执行一次,比如:加载解析自定义的配置文件.初始化数据库信息等等,在项目启动时就直接执行一些方法,可以减少很多繁琐的操作. 这里写了个简 ...
- 在web项目启动时,执行某个方法
在web项目中有很多时候需要在项目启动时就执行一些方法,而且只需要执行一次,比如:加载解析自定义的配置文件.初始化数据库信息等等,在项目启动时就直接执行一些方法,可以减少很多繁琐的操作. 在工作中遇到 ...
- springboot项目访问不到controller方法。
访问不到方法首先要从你的controller能否被扫描到出发, 图中显示创建springboot项目自带的这两个的文件要注意把他俩拿出来放到父包下面也就是图中这个位置.如果你的这两个文件在子包里或者说 ...
- Spring Boot学习--项目启动时执行特定方法
Springboot给我们提供了两种"开机启动"某些方法的方式:ApplicationRunner和CommandLineRunner. 这两种方法提供的目的是为了满足,在项目启动 ...
随机推荐
- python 多进程使用Queue通信的例子
import time from multiprocessing import Process,Queue MSG_QUEUE = Queue(5) def startA(msgQueue): whi ...
- 一次rna-seq的过程-知乎live转
数据分析流程 来自知乎孟浩巍的“快速入门生物信息学的”Live,超棒的~ 1.数据质控 首先是质控部分,使用fastqc进行对结果分析. 对于Illumia二代测序的结果质控包括两个方面,去掉测序质量 ...
- 吴超老师课程--Hive的介绍和安装
1.Hive1.1在hadoop生态圈中属于数据仓库的角色.他能够管理hadoop中的数据,同时可以查询hadoop中的数据. 本质上讲,hive是一个SQL解析引擎.Hive可以把SQL查询转换为 ...
- 解释一下python中的成员运算符
通过成员运算符‘in’ 和 ‘not in’,我们可以确认一个值是否是另一个值的成员 print('me' in 'disappointment')#True print('us' in 'disap ...
- JavaScript的消息机制
JavaScript本身是单线程的,但它却是事件驱动的.类似Windows窗体应用程序,它也需要消息队列机制来实现.程序的执行并不是连续的,绝大多数时间都在等待消息.每次执行执行程序都是在响应消息,这 ...
- Python3.x:日期库dateutil简介
Python3.x:日期库dateutil简介 安装 pip install python-dateutil 关于parser #字符串可以很随意,可以用时间日期的英文单词,可以用横线.逗号.空格等做 ...
- python图片文字识别笔记
我的环境为python3 坑比较多,在此做记录,以备查阅 命令行安装: pip install PIL pip install pytesseract pip install Pillow 下载tes ...
- 单片机、嵌入式CAN通信原理
工作原理: 单片机里内置了一个FIFO(先进先出)芯片,需要发送什么报文,就往这个芯片里写.比如有两个单片机作为CAN节点,A节点往自己的FIFO中写CAN报文,B节点往自己的FIFO中写CAN报文. ...
- 《React-Native系列》3、RN与native交互之Callback、Promise
接着上一篇<React-Native系列>RN与native交互与数据传递,我们接下来研究另外的两种RN与Native交互的机制 一.Callback机制 首先Calllback是异步的, ...
- [POI2009]Lyz
Description 初始时滑冰俱乐部有1到n号的溜冰鞋各k双.已知x号脚的人可以穿x到x+d的溜冰鞋. 有m次操作,每次包含两个数ri,xi代表来了xi个ri号脚的人.xi为负,则代表走了这么多人 ...