前言
本文为学习 Tomcat 的基础内容。
一、简介
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,它早期的名称为catalina,后来由Apache、Sun 和其他一些公司及个人共同开发而成,并更名为Tomcat。Tomcat 是一个小型的轻量级应用服务器,是应用(java)服务器,它只是一个servlet容器,是Apache的扩展,但它是独立运行的。
当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS、Apache等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。
在Tomcat中,应用程序的部署很简单,你只需将你的WAR放到Tomcat的webapp目录下,Tomcat会自动检测到这个文件,并将其解压。你在浏览器中访问这个应用的Jsp时,通常第一次会很慢,因为Tomcat要将Jsp转化为Servlet文件,然后编译。编译以后,访问将会很快。
Tomcat不仅仅是一个Servlet容器,它也具有传统的Web服务器的功能:处理Html页面。但是与Apache相比,它的处理静态Html的能力就不如Apache.我们可以将Tomcat和Apache集成到一块,让Apache处理静态Html,而Tomcat处理Jsp和Servlet.
优点:
(1)免费的
(2)占用系统资源比较小
(3)跨平台性好,有JAVA环境就行
(4) 开源
二、安装
1.配置JAVA环境
[root@tomcat ~]# tar xf jdk-7u67-linux-x64.tar.gz -C /usr/local
[root@tomcat ~]# ln -s /usr/local/jdk1.7.0_67/ /usr/local/jdk
[root@tomcat ~]# vim /etc/profile.d/jdk.sh
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
[root@tomcat ~]# source /etc/profile.d/jdk.sh
# 验证jdk安装
[root@tomcat ~]# java -version
java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
2.安装tomcat
[root@tomcat ~]# tar xf apache-tomcat-7.0.73.tar.gz
[root@tomcat ~]# mv apache-tomcat-7.0.73 /usr/local/tomcat
[root@tomcat ~]# cd /usr/local/tomcat/
[root@tomcat tomcat]# ls
bin conf lib LICENSE logs NOTICE RELEASE-NOTES RUNNING.txt temp webapps work
说明:
- bin 二进制命令:shutdown.sh 关闭tomcat;startup.sh启动tomcat
- lib 库目录 .jar
- logs 日志目录
- temp 临时文件
- work 运行JSP脚本需要的class文件
- conf 配置文件
- webapps 应用发布目录
3.启动tomcat
方法一:
[root@tomcat ~]# cd bin/
[root@tomcat ~]# ./startup.sh
[root@tomcat ~]# netstat -tanp |grep 8080
tcp 0 0 :::8080 :::* LISTEN 2045/java
方法二: system-V脚本:
[root@tomcat ~]# vim /etc/init.d/tomcat
#!/bin/bash
# Init file for Tomcat server daemon
JAVA_OPTS='-Xms64m -Xmx128m'
JAVA_HOME=/usr/local/jdk
CATALINA_HOME=/usr/local/tomcat
export JAVA_OPTS JAVA_HOME CATALINA_HOME
exec $CATALINA_HOME/bin/catalina.sh $1
问题: tomcat启动特别慢(PORT: 8005)
解决:
打开$JAVA_HOME/jre/lib/security/java.security这个文件,修改下面的内容:
securerandom.source=file:/dev/./urandom
三、配置文件
[root@tomcat ~]# vim /usr/local/tomcat/conf/server.xml
<?xml version='1.0' encoding='utf-8'?>
## 8005端口用于关闭tomcat,shutdown指定向端口发送的命令串
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.JasperListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
## 监听8080端口,负责建立HTTP连接。在通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个连接器
<Connector port="8080" protocol="HTTP/1.1"
## 连接超时时间数(毫秒)
connectionTimeout="20000"
## 指定服务器正在处理http请求时收到一个SSL传输请求后重定向的端口号
redirectPort="8443" />
## 监听8009端口,负责和apache服务器建立连接。在把Tomcat与apache集成时,需要用到这个连接器
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
## defaultHost指定默认虚拟主机
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
## Host标签定义虚拟主机
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
## 定义日志
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
四、基本优化
1.JVM内存优化
JAVA_OPTS="-XX:PermSize=256M -XX:MaxPermSize=512m -Xms4096m -Xmx4096m -Duser.timezone=Asia/Shanghai"
说明:
- -Xms:设置JVM初始内存大小(默认是物理内存的1/64)
- -Xmx:设置JVM可以使用的最大内存(默认是物理内存的1/4,建议:物理内存50%-80%)
- -XX:PermSize :为JVM启动时Perm的内存大小
- -XX:MaxPermSize :为最大可占用的Perm内存大小(默认为32M)
2.禁用AJP协议
注释 <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
ajp协议是tomcat为了动静资源处理分离时,通过该协议可以将css、js等静态资源请求转发到Apache的http服务器处理,提高并发量。
但是在优化tomcat时,没有用到Apache服务器,则需要将其禁用。
3.将BIO通讯模式修改为NIO通讯模式 (8以前的版本)
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" redirectPort="8443" />
其中,原来的protocol="HTTP/1.1"表示遵循http1.1协议,同时,也是一个最原始的未经优化的通信协议,修改之后的 protocol="org.apache.coyote.http11.Http11NioProtocol" ,表示以 NIO模式启动。
4.并发--启用外部连接池
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="500" minSpareThreads="4"/>
<Connector connectionTimeout="20000" port="8066" executor="tomcatThreadPool" protocol="org.apache.coyote.http11.Http11NioProtocol"/>
maxThreads:tomcat启动的最大线程数,即同时处理的任务个数,默认值为150
5.配置缓存
<Connector port="xxx" compression="on" compressionMinSize="2048" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" connectionTimeout="20000" disableUploadTimeout="true" />
说明:
- compression 打开压缩功能
- compressionMinSize 启用压缩的输出内容大小,这里面默认为2KB
- compressableMimeType 压缩类型
- connectionTimeout 定义建立客户连接超时的时间. 如果为 -1, 表示不限制建立客户连接的时间
6.优化连接器--最终模板
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="500" minSpareThreads="4"/>
<Connector port="8080" executor="tomcatThreadPool" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" enableLookups="false" maxPostSize="10485760" URIEncoding="UTF-8" useBodyEncodingForURI="true" maxConnections="1000" acceptCount="1000" minProcessors="100" maxProcessors="1000" disableUploadTimeout="true" compression="on" compressionMinSize="2048" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" SSLEnabled="false" />
说明:
- acceptCount:允许的最大连接数,应大于等于 maxProcessors ,默认值为 100
- enableLookups:是否反查域名,取值为: true 或 false 。为了提高处理能力,应设置为 false
- connectionTimeout:网络连接超时,单位:毫秒。设置为 0 表示永不超时,这样设置有隐患的。通常可设置为20000毫秒。
- disableUploadTimeOut:允许Servlet容器,正在执行使用一个较长的连接超时值,以使Servlet有较长的时间来完成它的执行,默认值为false
- maxPostSize:指定POST方式请求的最大量,没有指定默认为2097152
五、内核优化
Tomcat运行过程中可能会出现大量ESTABLISHED连接与Time_Wait连接
# netstat -tan | awk '/^tcp/ {++y[$NF]} END {for(w in y) print w, y[w]}'
CLOSE_WAIT 348
ESTABLISHED 1240
TIME_WAIT 5621 监控Apache与tomcat之间的链接端口
# netstat -n | grep 8009 | wc -l
7198
解决time_wait过多的问题:
通过调整内核参数:
# vim /etc/sysctl.conf #编辑文件,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
# /sbin/sysctl -p #让参数生效。
配置说明:
net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;
net.ipv4.tcp_fin_timeout=30 修改系統默认的 TIMEOUT 时间。
如果以上配置调优后性能还不理想,可继续修改一下配置:
# vi /etc/sysctl.conf
net.ipv4.tcp_keepalive_time = 1200
#表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.ip_local_port_range = 1024 65000
#表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。
net.ipv4.tcp_max_syn_backlog = 8192
#表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_tw_buckets = 5000
#表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。
默认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于 Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。
调优完毕,再压一下看看效果:
# netstat -tan | awk '/^tcp/ {++y[$NF]} END {for(w in y) print w, y[w]}'
ESTABLISHED 968