linux系统启动codesys linux系统启动特别慢的原因

admin2024-06-01  18

问题

这两天由于公司有个新项目,所以在阿里云购买了一些新的服务器,环境搭建完成之后,启动tomcat的时候发现巨慢,有图有真相:

linux系统启动codesys linux系统启动特别慢的原因,linux系统启动codesys linux系统启动特别慢的原因_系统调用,第1张

linux系统启动codesys linux系统启动特别慢的原因,linux系统启动codesys linux系统启动特别慢的原因_系统调用_02,第2张

可以看到启动的毫秒数有多久…

分析

为了找出原因,首先打印日志,把log4j2的日志层级全都打印了出来,但是没有发现有报错信息。之后我查看了一下启动进程,发现进程是启动了的,所以排除jvm退出引起的。那么,为什么程序会被阻塞呢?继续分析,我排除了CPU、内存不足引起的问题,排除了硬盘空间不足引起的问题,天呐️ 还是没有找到原因,接着分析,同一个环境在其他的服务器上是正常的(搭建的集群),所以几乎可以确定是linux服务器的原因。

确定是linux系统的原因,那么有一个命令strace,于是Google一下它的用法。

'' -c 统计每一系统调用的所执行的时间,次数和出错的次数等. 
'' -d 输出strace关于标准错误的调试信息. 
'' -f 跟踪由fork调用所产生的子进程. 
'' -ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号. 
'' -F 尝试跟踪vfork调用.在-f时,vfork不被跟踪. 
'' -h 输出简要的帮助信息. 
'' -i 输出系统调用的入口指针. 
'' -q 禁止输出关于脱离的消息. 
'' -r 打印出相对时间关于,,每一个系统调用. 
'' -t 在输出中的每一行前加上时间信息. 
'' -tt 在输出中的每一行前加上时间信息,微秒级. 
'' -ttt 微秒级输出,以秒了表示时间. 
'' -T 显示每一调用所耗的时间. 
'' -v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出. 
'' -V 输出strace的版本信息. 
'' -x 以十六进制形式输出非标准字符串 
'' -xx 所有字符串以十六进制形式输出. 
'' -a column 
'' 设置返回值的输出位置.默认 为40. 
'' -e expr 
'' 指定一个表达式,用来控制如何跟踪.格式如下: 
'' [qualifier=][!]value1[,value2]... 
'' qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用来限定的符号或数字.默认的 qualifier是 trace.感叹号是否定符号.例如: 
'' -eopen等价于 -e trace=open,表示只跟踪open调用.而-etrace!=open表示跟踪除了open以外的其他调用.有两个特殊的符号 all 和 none. 
'' 注意有些shell使用!来执行历史记录里的命令,所以要使用\. 
'' -e trace=set 
'' 只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all. 
'' -e trace=file 
'' 只跟踪有关文件操作的系统调用. 
'' -e trace=process 
'' 只跟踪有关进程控制的系统调用. 
'' -e trace=network 
'' 跟踪与网络有关的所有系统调用. 
'' -e strace=signal 
'' 跟踪所有与系统信号有关的 系统调用 
'' -e trace=ipc 
'' 跟踪所有与进程通讯有关的系统调用 
'' -e abbrev=set 
'' 设定 strace输出的系统调用的结果集.-v 等与 abbrev=none.默认为abbrev=all. 
'' -e raw=set 
'' 将指 定的系统调用的参数以十六进制显示. 
'' -e signal=set 
'' 指定跟踪的系统信号.默认为all.如 signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号. 
'' -e read=set 
'' 输出从指定文件中读出 的数据.例如: 
'' -e read=3,5 
'' -e write=set 
'' 输出写入到指定文件中的数据. 
'' -o filename 
'' 将strace的输出写入文件filename 
'' -p pid 
'' 跟踪指定的进程pid. 
'' -s strsize 
'' 指定输出的字符串的最大长度.默认为32.文件名一直全部输出. 
'' -u username 
'' 以username 的UID和GID执行被跟踪的命令

我用的是 strace -f -o strace.out ./catalina.sh run 命令。这样我们就能找到在哪一块被阻塞了。 strace 非常聪明它不仅仅给出了System Call还给出了传递的参数和返回值,read读取的是51号文件句柄,没有返回成功(unfinished)。 顺着这条路,我们看一下51号文件句柄是什么 /dev/random 是Linux下的随机函数生成器,读取它相当于生成随机数字。Google 一下终于知道原因了。

结论

其中Tomcat 的SessionId 是通过 SHA1算法计算得到的,在计算sessionId的时候必须有个秘钥,而这个秘钥就是随机数生成器生成的,所以现在有两种解决办法了。

第一种:通过修改Tomcat启动文件

修改Tomcat启动文件catalina.sh文件中加入 此行代码

-Djava.security.egd=file:/dev/urandom
第二种:通过修改JRE中的

$JAVA_PATH/jre/lib/security/java.security文件

securerandom.source=file:/dev/urandom

当然,前两种办法肯定不可靠,我的开发生涯中几乎没有这么改过tomcat的,再说jvm开发人员又不是二百五,他们没有选择/dev/urandom 肯定是有原因的,于是Google了一下,大略就是安全性的问题,如有兴趣可以自己去查看。那么第三种解决办法呼之欲出,那就是增增大/dev/random的熵池。

问题的原因是由于熵池不够大,所以增大它是最彻底的方法

第三种:增大熵池

查看熵池大小:

cat /proc/sys/kernel/random/entropy_avail

查看cpu是否支持:

cat /proc/cpuinfo | grep rdrand

一般都支持,如果不支持就用/dev/unrandom来做“熵源”。以Centos7为例:
安装熵工具:

yum install rngd-tools

启动

systemctl start rngd

指定路径

cp /usr/lib/systemd/system/rngd.service /etc/systemd/system

编辑

vim  /etc/systemd/system/rngd.service

配置

ExecStart=/sbin/rngd -f -r /dev/urandom

重载

systemctl daemon-reload

重启

systemctl restart rngd

说明

本文只做学习参考,如有任何不准确的地方欢迎指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明原文出处。如若内容造成侵权/违法违规/事实不符,请联系SD编程学习网:675289112@qq.com进行投诉反馈,一经查实,立即删除!