Tomcat高级介绍

2017年11月3日08:57:12Tomcat高级介绍已关闭评论 818 views

第1章 WEB站点部署

上线的代码有两种方式,第一种方式是直接将程序目录放在webapps目录下面。第二种方式是使用开发工具将程序打包成war包,然后上传到webapps目录下面,war包是使用java命令打的压缩包,类似zip、rar,并且能够被java程序解压。下面采用第二种方式:

1.1 使用war包部署测试web站点

1.1.1 上传war包

1.1.1.1 命令行上传war包

1
2
3
[root@centos7 ~]# mv /server/tools/memtest.war /usr/local/tomcat/webapps/
[root@centos7 ~]# ll /usr/local/tomcat/webapps/memtest.war
-rw-r--r-- 1 root root 643 Oct  8 09:25 /usr/local/tomcat/webapps/memtest.war

1.1.1.2 web界面上传war包

Tomcat高级介绍

Tomcat高级介绍

1.1.2 查看测试网站状态

Tomcat高级介绍

1.1.3 自定义默认网站目录

1.1.3.1 方法一:将站点放入默认站点目录下

将meminfo.jsp或其他程序放在tomcat/webapps/ROOT目录下即可。因为默认网站根目录为tomcat/webapps/ROOT,但如果有重名文件就不可以使用这种方式。

1.1.3.2 方法二:更改配置文件设置默认站点目录

  • 相当于nginx的location规则:
1
2
[root@centos7 ~]# vim /usr/local/tomcat/conf/server.xml
125       <Context path="" docBase="/usr/local/tomcat/webapps/memtest" debug="0" reloadable="false" crossContext="true"/>   # 添加此行,设置默认站点目录
  • 命令说明:
  1. Context:相当于location
  2. path="":后面可接任意路径(不一定是已有的目录结构,此处为空),只要访问的路径中有定义的字符串即访问"docBase"参数定义的目录或页面
  3. docBase="路径":实际访问的目录位置
  4. 修改配置文件后重启服务:
1
2
[root@centos7 ~]# /usr/local/tomcat/bin/shutdown.sh
[root@centos7 ~]# /usr/local/tomcat/bin/startup.sh
Tomcat高级介绍
提示:此处更改后的IP地址也相当于http://10.0.0.211:8080//meminfo.jsp

1.2 部署Jpress站点

jpress先当于java版本的wordpress,但它是一个半成品,不建议使用,仅作测试用即可。

PHP常用环境:Linux + Nginx + PHP + MySQL

JSP常用环境:Linux + Tomcat + JDK + MySQL(mariadb)

1.2.1 安装MySQL(Mariadb)

CentOS 7开始默认yum源内已经没有MySQL了,默认使用Mariadb代替MySQL。

1
2
[root@centos7 ~]# yum install -y mariadb-server
[root@centos7 ~]# systemctl start mariadb

1.2.2 创建Jpress用户和数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@centos7 ~]# mysql
<strong>Welcome to the MariaDB monitor.  Commands end with ; or \g.</strong>
<strong>Your MariaDB connection id is 2</strong>
<strong>Server version: 5.5.56-MariaDB MariaDB Server</strong>

<strong>Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.</strong>

<strong>Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.</strong>

MariaDB [(none)]> create database jpress DEFAULT CHARACTER SET utf8;
<strong>Query OK, 1 row affected (0.01 sec)</strong>

MariaDB [(none)]> grant all on jpress.* to jpress@'localhost' identified by '123456';
<strong>Query OK, 0 rows affected (0.00 sec)</strong>

MariaDB [(none)]> quit
<strong>Bye</strong>

1.2.3 上传站点到站点目录下

Tomcat高级介绍

提示:war文件上传到webapps目录后会自动解压,不需要自己手动解压。

1.2.4 更改Jpress目录名称

1
[root@centos7 ~]# mv /usr/local/tomcat/webapps/jpress-web-newest /usr/local/tomcat/webapps/jpress

1.2.5 web界面安装Jpress

Tomcat高级介绍

Tomcat高级介绍

Tomcat高级介绍

Tomcat高级介绍

1.2.6 重启Tomcat

1
2
[root@centos7 ~]# /usr/local/tomcat/bin/shutdown.sh
[root@centos7 ~]# /usr/local/tomcat/bin/startup.sh

1.2.7 查看安装情况

Tomcat高级介绍

Tomcat高级介绍

Tomcat高级介绍

第2章 Tomcat多实例及集群架构

  • 多虚拟主机:使用Nginx
  • 多实例:使用Tomcat目的是尽可能地使用我们系统的资源(资源相对多时使用多实例)
提示:Tomcat非常耗内存,所以只有资源足够多的时候再使用多实例,否则会导致系统资源枯竭。

2.1 Tomcat多实例安装配置

2.1.1 重新二进制安装Tomcat

1
2
3
4
[root@centos7 ~]# cd /server/tools/
[root@centos7 tools]# tar xf apache-tomcat-8.0.47.tar.gz
[root@centos7 tools]# cp -a apache-tomcat-8.0.47/ /usr/local/tomcat8_1
[root@centos7 tools]# cp -a apache-tomcat-8.0.47/ /usr/local/tomcat8_2

2.1.2 修改配置文件

1
2
3
# 更改每个实例的关闭端口和监听端口
[root@centos7 ~]# sed -i 's#8005#8011#;s#8080#8081#' /usr/local/tomcat8_1/conf/server.xml
[root@centos7 ~]# sed -i 's#8005#8012#;s#8080#8082#' /usr/local/tomcat8_2/conf/server.xml

2.1.3 打包多实例文件

提示:打包多实例文件是为了之后便于批量管理和分发,此为生产环境经验。
1
2
[root@centos7 tools]# cd /usr/local/
[root@centos7 local]# tar zcf tomcat_muti.tar.gz ./tomcat8_1 ./tomcat8_2

2.1.4 启动多实例

1
2
3
4
[root@centos7 ~]# for i in {1..2};do /usr/local/tomcat8_$i/bin/startup.sh;done
[root@centos7 ROOT]# netstat -lntup | egrep "8081|8082"
tcp6       0      0 :::8081                 :::*                    LISTEN      4365/java          
tcp6       0      0 :::8082                 :::*                    LISTEN      4764/java

2.2 使用nginx反向代理访问Tomcat多实例

2.2.1 yum安装nginx

1
2
3
4
5
6
7
[root@centos7 ~]# yum install -y nginx
[root@centos7 ~]# nginx -V
nginx version: nginx/1.10.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC)
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-google_perftools_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'

2.2.2 编辑nginx配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@centos7 ~]# vim /etc/nginx/nginx.conf
 38     upstream web_pools {            # 添加upstram区块
 39         server 10.0.0.211:8082;
 40         server 10.0.0.211:8081;
 41     }
 42
 43     server {
 44         listen       80 default_server;
 45         listen       [::]:80 default_server;
 46         server_name  _;
 47         root         /usr/share/nginx/html;
 48
 49         # Load configuration files for the default server block.
 50         include /etc/nginx/default.d/*.conf;
 51
 52         location / {                # 编辑location区块
 53                 index index.jsp index.html index.htm;
 54                 proxy_pass http://web_pools;
 55         }

2.2.3 检查并启动nginx

1
2
3
4
[root@centos7 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@centos7 ~]# systemctl start nginx

2.2.4 查看测试网站

Tomcat高级介绍

Tomcat高级介绍

第3章 Tomcat监控

3.1 Tomcat自带函数监控

3.1.1 监控代码

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@centos7 ~]# vim /usr/local/tomcat/webapps/memtest/meminfo.jsp
<%
Runtime rtm = Runtime.getRuntime();
long mm = rtm.maxMemory()/1024/1024;
long tm = rtm.totalMemory()/1024/1024;
long fm = rtm.freeMemory()/1024/1024;

out.println("JVM memory detail info :<br>");
out.println("Max memory:"+mm+"MB"+"<br>");
out.println("Total memory:"+tm+"MB"+"<br>");
out.println("Free memory:"+fm+"MB"+"<br>");
out.println("Available memory can be used is :"+(mm+fm-tm)+"MB"+"<br>");
%>

3.1.2 监控结果

Tomcat高级介绍

3.2 jps命令

【命令说明】:jps是jdk包自带的命令,jps主要用来输出JVM中运行的进程状态信息。

【语法格式】

jps [ options ] [ hostid ] (如果不指定hostid就默认为当前主机或服务器)

【参数说明】:

  • -q:不输出类名、JAR名和传入main方法的参数
  • -m:输出传入main方法的参数
  • -l:输出main类或JAR的全名
  • -v:输出传入JVM的参数

【命令示例】:

1
2
3
4
5
6
[root@centos7 ~]# jps -lvm      # 可以快速获取Java进程的PID,不用ps和grep命令
4993 sun.tools.jps.Jps -lvm -Denv.class.path=.:/usr/local/jdk/lib:/usr/local/jdk/jre/lib:/usr/local/jdk/lib/tools.jar -Dapplication.home=/usr/local/jdk1.8.0_144 -Xms8m
2211 org.apache.catalina.startup.Bootstrap start -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp
2826 org.apache.catalina.startup.Bootstrap start -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp
4764 org.apache.catalina.startup.Bootstrap start -Djava.util.logging.config.file=/usr/local/tomcat8_2/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Djava.endorsed.dirs=/usr/local/tomcat8_2/endorsed -Dcatalina.base=/usr/local/tomcat8_2 -Dcatalina.home=/usr/local/tomcat8_2 -Djava.io.tmpdir=/usr/local/tomcat8_2/temp
4365 org.apache.catalina.startup.Bootstrap start -Djava.util.logging.config.file=/usr/local/tomcat8_1/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=10.0.0.211 -Djava.endorsed.dirs=/usr/local/tomcat8_1/endorsed -Dcatalina.base=/usr/local/tomcat8_1 -Dcatalina.home=/usr/local/tomcat8_1 -Djava.io.tmpdir=/usr/local/tomcat8_1/temp

3.3 jstack命令

【命令说明】:jstack主要用来查看某个Java进程内的线程堆栈信息

【语法格式】

1
2
3
       jstack [ options ] pid
       jstack [ options ] executable core
       jstack [ options ] [ server-id@ ] remote-hostname-or-IP

【参数说明】:

  • -l long listings:会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况
  • -m mixed mode:不仅会输出Java堆栈信息,还会输出C/C++堆栈信息(比如Native方法)
提示:jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,所以它在JVM性能调优中使用的非常多。

3.4 jmap

【命令说明】:jmap用来查看堆内存使用状况,一般结合jhat(Java Heap Analysis Tool)使用

【语法格式】:

1
2
3
       jmap [ options ] pid
       jmap [ options ] executable core
       jmap [ options ] [ pid ] server-id@ ] remote-hostname-or-IP

如果运行在64位JVM上,可能需要指定-J-d64命令选项参数。

【参数说明】:

  • jmap -permstat pid:打印进程的类加载器和类加载器加载的持久代对象信息,输出类加载器名称、对象是否存活(不可靠)、对象地址、父类加载器、已加载的类大小等信息。
  • jmap -heap pid:查看进程堆内存使用情况,包括使用的GC算法、堆配置参数和各代中堆内存使用情况。

3.5 jconsole和jvisualvm

3.5.1 下载安装jconsole和jvisualvm

这两个是windows下的图形监控工具,需要安装Java SE Development Kit:

Tomcat高级介绍

3.5.2 Tomcat开启远程监控功能

3.5.2.1 编辑catalina配置文件

1
2
3
4
5
6
7
[root@centos7 ~]# vim /usr/local/tomcat8_1/bin/catalina.sh
106 CATALINA_OPTS="$CATALINA_OPTS
107 -Dcom.sun.management.jmxremote
108 -Dcom.sun.management.jmxremote.port=12345
109 -Dcom.sun.management.jmxremote.authenticate=false
110 -Dcom.sun.management.jmxremote.ssl=false
111 -Djava.rmi.server.hostname=10.0.0.211"

3.5.2.2 添加主机名解析

1
2
3
4
[root@centos7 ~]# vim /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.211   centos7

3.5.2.3 重启Tomcat

1
2
[root@centos7 ~]# /usr/local/tomcat8_1/bin/shutdown.sh
[root@centos7 ~]# /usr/local/tomcat8_1/bin/startup.sh

3.5.2.4 查看端口是否打开

1
2
3
[root@centos7 ~]# lsof -i:12345
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
java    4365 root   20u  IPv6  30348      0t0  TCP *:italk (LISTEN)

3.5.3 使用jconsole

Tomcat高级介绍

Tomcat高级介绍

Tomcat高级介绍

3.5.4 使用jvisualvm

3.5.4.1 添加监控主机

Tomcat高级介绍

Tomcat高级介绍

Tomcat高级介绍

Tomcat高级介绍

Tomcat高级介绍

3.5.4.2 导出java堆栈信息

Tomcat高级介绍

Tomcat高级介绍

Tomcat高级介绍

3.5.4.3 读取java堆栈信息

1
[root@centos7 ~]# sz /usr/local/tomcat8_1/temp/heapdump-1508931950909.hprof

Tomcat高级介绍

Tomcat高级介绍

Tomcat高级介绍

3.6 zabbix监控

提示:zabbix编译安装时需要添加--enable-java支持此功能。
1
请参看《zabbix介绍》第12章监控Tomcat。

第4章 Tomcat安全优化和性能优化

4.1 安全优化

4.1.1 降权启动

4.1.1.1 添加tomcat普通用户

1
2
3
4
5
6
[root@centos7 ~]# useradd tomcat
[root@centos7 ~]# cp -a /usr/local/tomcat /home/tomcat/
[root@centos7 ~]# chown -R tomcat.tomcat /home/tomcat/tomcat/
[root@centos7 ~]# ll /home/tomcat/
total 0
lrwxrwxrwx 1 root root 32 Oct 24 12:59 tomcat -> /usr/local/apache-tomcat-8.0.47/

4.1.1.2 使用普通用户启动tomcat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@centos7 ~]# su - tomcat
[tomcat@centos7 ~]$ ls
tomcat
[tomcat@centos7 ~]$ tomcat/bin/startup.sh
Using CATALINA_BASE:   /home/tomcat/tomcat
Using CATALINA_HOME:   /home/tomcat/tomcat
Using CATALINA_TMPDIR: /home/tomcat/tomcat/temp
Using JRE_HOME:        /usr/local/jdk
Using CLASSPATH:       /home/tomcat/tomcat/bin/bootstrap.jar:/home/tomcat/tomcat/bin/tomcat-juli.jar
Tomcat started.

[tomcat@centos7 ~]$ ps -ef | grep tomcat
root       5596   4612  0 22:12 pts/0    00:00:00 su - tomcat
tomcat     5597   5596  0 22:12 pts/0    00:00:00 -bash
tomcat     5630      1 28 22:12 pts/0    00:00:01 /usr/local/jdk/bin/java -Djava.util.logging.config.file=/home/tomcat/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=10.0.0.211 -Djava.endorsed.dirs=/home/tomcat/tomcat/endorsed -classpath /home/tomcat/tomcat/bin/bootstrap.jar:/home/tomcat/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/home/tomcat/tomcat -Dcatalina.home=/home/tomcat/tomcat -Djava.io.tmpdir=/home/tomcat/tomcat/temp org.apache.catalina.startup.Bootstrap start
tomcat     5649   5597  0 22:13 pts/0    00:00:00 ps -ef
tomcat     5650   5597  0 22:13 pts/0    00:00:00 grep --color=auto tomcat

4.1.1.3 加入开机自启动(可选)

1
[tomcat@centos7 ~]$ echo "su - tomcat -c '/home/tomcat/tomcat8_2/bin/startup.sh'" >> /etc/rc.local

4.1.2 telnet管理端口保护

更改管理端口端口号:

1
2
3
4
[root@centos7 ~]# vim /usr/local/tomcat/conf/server.xml
 69     <Connector port="8888" protocol="HTTP/1.1"
 70                connectionTimeout="20000"
 71                redirectPort="8443" />

4.1.3 ajp连接端口保护(8009)

注释ajp连接语句:

1
2
[root@centos7 ~]# vim /usr/local/tomcat/conf/server.xml
 91     <!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->

4.1.4 禁用管理端

删除管理页面文件:

1
2
[root@centos7 ~]# mv /usr/local/tomcat/webapps/* /tmp
[root@centos7 ~]# mkdir -p /usr/local/tomcat/webapps/ROOT

4.2 性能优化

4.2.1 屏蔽dns查询enableLookups="false"

1
2
3
4
[root@centos7 ~]# vim /usr/local/tomcat/conf/server.xml
 91   <Connector  port="8081" protocol="HTTP/1.1"
 92              connectionTimeout="6000" enableLookups="false" acceptCount="800"
 93              redirectPort="8443" />

4.2.2 jvm调优

Tomcat消耗内存很多,如果系统资源有限,那就需要进行调优,提高资源使用率。

1
2
3
4
[root@centos7 ~]# vim /usr/local/tomcat/bin/catalina.sh
# 优化catalina.sh配置文件。在catalina.sh配置文件中添加以下代码:
616 JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx1024m -XX
:NewSize=512m -XX:MaxNewSize=512m"
  • 命令说明:
  1. server:一定要作为第一个参数,在多个CPU时性能佳
  2. -Xms:初始堆内存Heap大小,使用的最小内存,cpu性能高时此值应设的大一些
  3. -Xmx:初始堆内存heap最大值,使用的最大内存
  4. 上面两个值是分配JVM的最小和最大内存,取决于硬件物理内存的大小,建议均设为物理内存的一半。
  5. -XX:PermSize:设定内存的永久保存区域,tomcat8已经弃用。
  6. -XX:MaxPermSize:设定最大内存的永久保存区域,tomcat8已经弃用。
  7. -XX:MaxNewSize:
  8. -Xss 15120 这使得JBoss每增加一个线程(thread)就会立即消耗15M内存,而最佳值应该是128K,默认值好像是
  9. +XX:AggressiveHeap 会使得 Xms没有意义。这个参数让jvm忽略Xmx参数,疯狂地吃完一个G物理内存,再吃尽一个G的swap。
  10. -Xss:每个线程的Stack大小
  11. -verbose:gc 现实垃圾收集信息
  12. -Xloggc:gc.log 指定垃圾收集日志文件
  13. -Xmn:young generation的heap大小,一般设置为Xmx的3、4分之一
  14. -XX:+UseParNewGC :缩短minor收集的时间
  15. -XX:+UseConcMarkSweepGC :缩短major收集的时间

第5章 企业案例

5.1 Tomcat在CentOS7启动慢的解决办法

【问题现象】:

在CentOS启动Tomcat时,启动过程很慢,需要几分钟,经过查看日志,发现耗时在这里:是session引起的随机数问题导致的。Tocmat的Session ID是通过SHA1算法计算得到的,计算Session ID的时候必须有一个密钥。为了提高安全性Tomcat在启动的时候回通过随机生成一个密钥。

1
2
3
4
22-Apr-2017 19:33:07.623 INFO [localhost-startStop-1] org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom Creation of
 SecureRandom instance for session ID generation using [SHA1PRNG] took [55,507] milliseconds.
22-Apr-2017 19:33:07.653 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web appli
cation directory /application/apache-tomcat-8.0.27/webapps/ROOT has finished in 55,935 ms

【原因分析】:

主要原因是生成随机数的时候卡住了,导致tomcat启动不了。是否有足够的熵来用于产生随机数,可以通过如下命令来查看:

1
2
[root@centos7 ~]# cat /proc/sys/kernel/random/entropy_avail
132

为了加速/dev/random提供随机数的速度,可以通过操作设备的外设,让其产生大量的中断(如网络传输数据,按键,移动鼠标,在命令行敲几个不同的命令,俗称聚气。(cat /dev/random 会消耗能量)

【解决方法】:

  • 方法1:更改security文件
1
2
3
4
[root@centos7 ~]# vim $JAVA_HOME/jre/lib/security/java.security
117 securerandom.source=file:/dev/random
# 改为
securerandom.source=file:/dev/urandom
  • 方法2:更改sh文件
1
2
3
4
[root@centos7 ~]# vim $TOMCAT_HOME/bin/catalina.sh
if [[ "$JAVA_OPTS" != *-Djava.security.egd=* ]]; then
    JAVA_OPTS="$JAVA_OPTS -Djava.security.egd=file:/dev/urandom"
fi

这个系统属性egd表示熵收集守护进程(entropy gathering daemon)

  • 方法3:安装rng并自动生成随机数
1
2
3
4
[root@centos7 ~]# yum install -y rng-tools      # 安装rngd服务(熵服务,增大熵池)
[root@centos7 ~]# systemctl start rngd          # 启动服务
[root@centos7 ~]# cat /proc/sys/kernel/random/entropy_avail
2982                                            # 产生的值在2900-3100之间
提示:centos7 rngd.service启动失败的解决方法:http://blog.csdn.net/shile/article/details/52661660

5.2 Tomcat日志文件占满磁盘的解决办法

【问题现象】:

当访问量增大时,Tomcat的日志文件急剧增加导致磁盘空间不足。

【原因分析】:

Tomcat会将详细的记录用户操作,所以日志文件巨大且增长速度极快。

【解决方法】:

  • 方法1:创建定时任务定时清理Tomcat的日志文件
1
2
3
[root@centos7 ~]# crontab -l
# clean tomcat logs
* */2 * * * >/usr/local/tomcat/logs/catalina.out &>/dev/null
  • 方法3:移除日志目录
1
此方法未作检验

5.3 企业案例:Linux下java/http进程高解决案例

生产环境下某台Tomcat7服务器在刚发布时一切正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高。

【解决思路】:

  • 查找进程高的PID
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@centos7 ~]# top -H
top - 20:51:17 up  8:01,  1 user,  load average: 0.00, 0.01, 0.05
Threads: 505 total,   1 running, 504 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni, 99.9 id,  0.1 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   485280 total,    11112 free,   383040 used,    91128 buff/cache
KiB Swap:  1048572 total,   579012 free,   469560 used.    62144 avail Mem

   PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                        
  2221 root      20   0 3726344  46928   3100 S  0.3  9.7   0:22.10 java                  
  3615 root      20   0       0      0      0 S  0.3  0.0   0:03.22 kworker/2:3          
  5054 root      20   0  146572   2460   1428 R  0.3  0.5   0:00.09 top                  
     1 root      20   0   41320   2036   1212 S  0.0  0.4   0:03.38 systemd  
...省略部分输出内容...
  • 查看这个进程所有系统调用
1
2
3
4
5
6
[root@centos7 ~]# strace -p 2221
Process 2221 attached
restart_syscall(<... resuming interrupted call ...>) = -1 ETIMEDOUT (Connection timed out)
futex(0x7f1c0c0c4128, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f1c0c0c4154, FUTEX_WAIT_BITSET_PRIVATE, 1, {29075, 276426973}, ffffffff) = -1 ETIMEDOUT (Connection timed out)
...省略部分输出内容...
  • 如果是web应用可以继续打印线程的堆栈信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@centos7 ~]# printf "%x\n" 2221            # 将需要的线程ID转换为16进制格式
8ad
[root@centos7 ~]# jstack 2221 | grep 8ad -A 30
# 或使用脚本直接打印线程信息
[root@centos7 ~]# sh show-busy-java-threads.sh # 此脚本可以打印前5名占用资源最多的java线程
[1] Busy(0.0%) thread(4795/0x12bb) stack of java process(4764) under user(root):
"http-nio-8082-Acceptor-0" #29 daemon prio=5 os_prio=0 tid=0x00007fd41049c800 nid=0x12bb runnable [0x00007fd3ec8c9000]
   java.lang.Thread.State: RUNNABLE
    at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
    at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
    at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
    - locked <0x00000000fafe0e70> (a java.lang.Object)
    at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:692)
    at java.lang.Thread.run(Thread.java:748)
[2] Busy(0.0%) thread(4794/0x12ba) stack of java process(4764) under user(root):
"http-nio-8082-ClientPoller-1" #28 daemon prio=5 os_prio=0 tid=0x00007fd41049a000 nid=0x12ba runnable [0x00007fd3ec9ca000]
weinxin
我的微信
如果有技术上的问题可以扫一扫我的微信