今天在部署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方法时进入慢的问题的更多相关文章

  1. SpringBoot项目打成Jar包时运行

    使用java -jar ***.jar执行jar包的时候,会找jar包中的main()方法. 对于SpringBoot项目的Jar包,在META-INF目录下的MANIFEST.MF文件中,Main- ...

  2. netty笔记-:Channel与ChannelHandlerContext执行write方法的区别

      在netty中有我们一般有两种发送数据的方式,即使用ChannelHandlerContext或者Channel的write方法,这两种方法都能发送数据,那么其有什么区别呢.这儿引用netty文档 ...

  3. Mybatis:解决调用带有集合类型形参的mapper方法时,集合参数为空或null的问题

    此文章有问题,待修改! 使用Mybatis时,有时需要批量增删改查,这时就要向mapper方法中传入集合类型(List或Set)参数,下面是一个示例. // 该文件不完整,只展现关键部分 @Mappe ...

  4. springboot 学习之路 9 (项目启动后就执行特定方法)

    目录:[持续更新.....] spring 部分常用注解 spring boot 学习之路1(简单入门) spring boot 学习之路2(注解介绍) spring boot 学习之路3( 集成my ...

  5. C#编译器优化那点事 c# 如果一个对象的值为null,那么它调用扩展方法时为甚么不报错 webAPI 控制器(Controller)太多怎么办? .NET MVC项目设置包含Areas中的页面为默认启动页 (五)Net Core使用静态文件 学习ASP.NET Core Razor 编程系列八——并发处理

    C#编译器优化那点事   使用C#编写程序,给最终用户的程序,是需要使用release配置的,而release配置和debug配置,有一个关键区别,就是release的编译器优化默认是启用的.优化代码 ...

  6. 在web项目启动时,使用监听器来执行某个方法

    在web项目中有很多时候需要在项目启动时就执行一些方法,而且只需要执行一次,比如:加载解析自定义的配置文件.初始化数据库信息等等,在项目启动时就直接执行一些方法,可以减少很多繁琐的操作. 这里写了个简 ...

  7. 在web项目启动时,执行某个方法

    在web项目中有很多时候需要在项目启动时就执行一些方法,而且只需要执行一次,比如:加载解析自定义的配置文件.初始化数据库信息等等,在项目启动时就直接执行一些方法,可以减少很多繁琐的操作. 在工作中遇到 ...

  8. springboot项目访问不到controller方法。

    访问不到方法首先要从你的controller能否被扫描到出发, 图中显示创建springboot项目自带的这两个的文件要注意把他俩拿出来放到父包下面也就是图中这个位置.如果你的这两个文件在子包里或者说 ...

  9. Spring Boot学习--项目启动时执行特定方法

    Springboot给我们提供了两种"开机启动"某些方法的方式:ApplicationRunner和CommandLineRunner. 这两种方法提供的目的是为了满足,在项目启动 ...

随机推荐

  1. appium 中部分 api 的使用方法

    使用的语言是java,appium的版本是1.3.4,java-client的版本是java-client-2.1.0,建议多参考java-client-2.1.0-javadoc. 1.使用Andr ...

  2. redmine集成git

    步骤: redmine服务器 1.  在下载安装GIT客户端 下载地址: https://git-scm.com/ 2.    在redmine服务器上将对应项目的git镜像到本地(不是源码下载到本地 ...

  3. kubernetes --> kube-dns 安装

    准备yaml文件: 1.kubedns-cm.yaml # Copyright 2016 The Kubernetes Authors. # # Licensed under the Apache L ...

  4. Java程序设计专题

  5. HandlerSocket ---MySQL与NoSQL ---SQL与NoSQL的融合(转)

    项目地址:https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL 写这一篇内容的原因是MySQL5.6.2突然推出了memcached的功能 ...

  6. js 性能优化 篇一

    JS性能优化 摘自:http://www.china125.com/design/js/3631.htm  首先,由于JS是一种解释型语言,执行速度要比编译型语言慢得多.(注:,Chrome是第一款内 ...

  7. hadoop---Java 网络IO编程总结BIO、NIO、AIO

    转载请注明出处:http://blog.csdn.net/anxpp/article/details/51512200,谢谢! 本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解 ...

  8. mysql中int(M) tinyint(M)中M的作用

    原先对mysql不太理解,但也没有报错.但理解的不够深入.这次补上. 原来以为int(11)是指11个字节,int(10)就是10个字节.我错了. http://zhidao.baidu.com/li ...

  9. 20145235李涛《网络对抗》逆向及Bof基础

    上学期实验楼上做过这个实验 直接修改程序机器指令,改变程序执行流程 首先进行反汇编   我们所要修改的是,程序从foo返回,本来要返回到80484ba,而我们要把80484ba修改为getshell的 ...

  10. 解决You have new mail in /var/spool/mail/root提示

    终端远程登陆后经常提示You have new mail in /var/spool/mail/root 这个提示是LINUX会定时查看LINUX各种状态做汇总,每经过一段时间会把汇总的信息发送的ro ...