今天在部署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. MySQL 数据类型(Day41)

    一.介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的高度,但宽度是可选的. mysql数据类型概览 #1.数字:(默认都是有符号,宽度指的是显示宽度,与存储无关) ...

  2. Delphi 正则表达式之TPerlRegEx 类的属性与方法(2): 关于子表达式

    Delphi 正则表达式之TPerlRegEx 类的属性与方法(2): 关于子表达式 // MatchedExpression 与 SubExpressions[0] var   reg: TPerl ...

  3. ORA-00911: 无效字符\n

    使用EXECUTE IMMEDIATE执行命令时命令字符串不能添加命令结束符";",否则会报此错

  4. GIT学习笔记(4):远程分支

    GIT学习笔记(4):远程分支 远程分支 远程分支是什么 远程分支是对远程仓库中的分支的索引.它们是一些无法移动的本地分支:只有在GIT进行网络交互时才会更新.远程分支就是书签,提醒着你上次连接远程仓 ...

  5. Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) E. Tree Folding

    地址:http://codeforces.com/contest/765/problem/E 题目: E. Tree Folding time limit per test 2 seconds mem ...

  6. hdu 1686 Oulipo kmp算法

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1686 题目: Problem Description The French author George ...

  7. iOS 和服务端交互 数据加密策略

    总体逻辑: 客户端:对称加密数据,上传...回执对称解密 同理服务端:获取上传数据 对称解密 ...下发:对称加密 当且仅当登录接口和 拉新(更新nonce 和 key的接口)是对称加密上传 非对称解 ...

  8. Generative model 和Discriminative model

    学习音乐自动标注过程中设计了有关分类型模型和生成型模型的东西,特地查了相关资料,在这里汇总. http://blog.sina.com.cn/s/blog_a18c98e50101058u.html ...

  9. Node单线程与异步编程的初步理解

    最近学习了一些关于node的单线程与异步的知识,想拿过来和大家分享下: var async = require('async') //并行无关联,等待事件为最长时间请求过程.如以下两个任务执行时间 c ...

  10. 强大的jQuery幻灯片播放插件 支持全拼、拖拽和下载等功能

    在线演示 本地下载