tomcat生产环境部署

实验环境介绍

实验环境规划

主机名 ip address 操作系统 职责
linux-node1 192.168.56.11 centos7 tomcat
1
2
3
4
5
6
[root@linux ~]# uname -r
3.10.0-229.el7.x86_64
[root@linux ~]# uname -m
x86_64
[root@linux ~]# cat /etc/redhat-release
CentOS Linux release 7.1.1503 (Core)

tomcat安装过程

先安装java环境

1
2
3
4
5
6
7
8
9
10
11
12
13
cd /usr/local/src/
tar -zxf jdk-8u65-linux-x64.tar.gz ##从官网下载好java包,上传到这个目录中。
mv jdk1.8.0_65/ /data/app/
ln -s /data/app/jdk1.8.0_65/ /data/app/java
vim /etc/profile
###setup java by biglittleant at 2015-08-28
export JAVA_HOME=/data/app/java
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar

source /etc/profile##生效一下java版本

安装tomcat

1
2
3
4
5
6
7
8
9
10
11
cd /usr/local/src/
tar -zxf apache-tomcat-8.0.32.tar.gz
mv apache-tomcat-8.0.32 /data/app/
ln -s /data/app/apache-tomcat-8.0.32/ /data/app/tomcat
useradd -d /data/app/tomcat -u 505 tomcat
passwd tomcat
chown -R tomcat.tomcat /data/app/apache-tomcat-8.0.32/
cd /data/app/tomcat/
chmod 744 -R bin/*.sh
su - tomcat
pwd

手动编写tomcat启停脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#!/bin/bash

TOMCAT_PATH=/data/app/tomcat

usage(){
echo "Usage: $0 [start|stop|status|restart]"
}

status_tomcat(){

ps aux | grep java | grep tomcat | grep -v 'grep'

}

start_tomcat(){
/data/app/tomcat/bin/startup.sh
}

stop_tomcat(){

TPID=$(ps aux | grep java | grep tomcat | grep -v 'grep' | awk '{print $2}')
kill -9 $TPID
sleep 5;

TSTAT=$(ps aux | grep java | grep tomcat | grep -v 'grep' | awk '{print $2}')
if [ -z $TSTAT ];then
echo "tomcat stop"
else
kill -9 $TSTAT
fi

cd $TOMCAT_PATH

rm temp/* -rf
rm work/* -rf

}

main(){
case $1 in

start)
start_tomcat;;
stop)
stop_tomcat;;
status)
status_tomcat;;
restart)
stop_tomcat && start_tomcat;;
*)
usage;
esac

}

main $1

配置server.xml

tomcat的server.xml 配置文件一共分为五大部分:

  • server块
  • service块
  • connector块
  • engine块
  • host块
    下图是我看到比较好的一张解释server.xml配置文件的图片
    tomcat-配置文件结构图

看懂配置文件以后我们来说明一下tomcat处理客户端请求的过程

  1. 客户端访问URL:http://www.biglittleant.cn:8080/java/index.jsp 服务器端收到请求以后,开始解析URL。
  2. connector块创建8080端口,并接收客户端的请求地址,交给engine块。
  3. engine会根据域名(www.biglittleant.cn)读取相应的host块。
  4. host块接到请求后,分析URI(/java/index.jsp)匹配相应的context块。然后跳转到context段docBase的目录,并读取index.jsp,返回给engine。
  5. engine返回给connector。
  6. connector把结果返回给客户端。

server.xml 配置文件详细解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?xml version='1.0' encoding='utf-8'?>

<Server port="8888" shutdown="shutdowntomcat">
###开启8888管理端口,设定shutdowntomcat可以关闭tomcat服务器。
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JasperListener" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />


<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">
##定义一个service

<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
##开启一个8080端口,来接收客户端请求,使用HTTP/1.1协议,超时时间为20000,redirectPort 是SSL的端口,也可以不配置。
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
##同上。协议改变了。

<Engine name="Catalina" defaultHost="localhost">
#defaultHost 定义默认host主机,当所有host都匹配不了URL时,将转发给localhost虚拟主机。
<Realm className="org.apache.catalina.realm.LockOutRealm">

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>

<Host name="localhost" appBase="webapps"
unpackWARs="false" autoDeploy="false">
##定义web应用程序的目录,关闭自动解压wAR包,关闭自动部署。生产上一定要关闭。否则会发生意想不到的问题。
<Context path="/java" docBase="/data/app/tomcat/webapps/java" debug="0" reloadable="false" crossContext="true"/>
##定义一个路径,当URI中包含/java时去,docbase路径下来查找相应的配置文件,reloadable=True时,会监控docbase路径下的文件是否发生改变,发生改变就自动重载配置,生产上这个也要禁止掉。

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t %r %s %b %{Referer}i %{User-Agent}i %D" resolveHosts="false" />
##定义本host的accesslog的文件名(localhost_access_log),后缀名(.txt)pattern 定义如何记录accesslog。

</Host>
</Engine>
</Service>
</Server>

配置web.xml

1
2
3
4
5
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
#关闭服务器的list目录的文件内容。

删除tomcat的默认文件

1
2
3
4
rm -f tomcat/webapps/*
rm -f tomcat/conf/tomcat-user.xml
去除其他用户对tomcat 起停脚本的执行权限
chmod 744 /bin/*.sh

调优JAVA,开启JVM监控

1
2
3
4
5
6
7
8
9
10
vim tomcat/bin/catalina.sh
JAVA_OPTS="-XX:PermSize=64M -XX:MaxPermSize=128m -Xms512m -Xmx512m -Duser.timezone=Asia/Shanghai"
## 配置服务器的jvm参数调优
export CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote"
export CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.port=10053"
export CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
export CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
export CATALINA_OPTS="$CATALINA_OPTS -Djava.rmi.server.hostname=192.168.56.11"
##开启服务器的远程JVM端口
236 # ----- Execute The Requested Command -----------------------------------------

剩下的问题就是开启zabbix监控tomcat的JVM。

补充如何查看tomcat的jmx选项

JMX 有很多 Key 可以监控,具体的值,可以通过 jconsole 参看。如下图所示,如果要监控线程数,就可以写成 jmx[“java.lang:type=Threading”, “ThreadCount”]

Tomcat 日志配置

pattern属性值由字符串常量和pattern标识符加上前缀”%”组合而成。pattern标识符加上前缀”%”,用来代替当前请求/响应中的对应的变量值。目前支持如下的pattern:

  • %a - 远端IP地址
  • %A - 本地IP地址
  • %b - 发送的字节数,不包括HTTP头,如果为0,使用”-”
  • %B - 发送的字节数,不包括HTTP头
  • %h - 远端主机名(如果resolveHost=false,远端的IP地址)
  • %H - 请求协议
  • %l - 从identd返回的远端逻辑用户名(总是返回 ‘-‘)
  • %m - 请求的方法(GET,POST,等)
  • %p - 收到请求的本地端口号
  • %q - 查询字符串(如果存在,以 ‘?’开始)
  • %r - 请求的第一行,包含了请求的方法和URI
  • %s - 响应的状态码
  • %S - 用户的session ID
  • %t - 日志和时间,使用通常的Log格式
  • %u - 认证以后的远端用户(如果存在的话,否则为’-‘)
  • %U - 请求的URI路径
  • %v - 本地服务器的名称
  • %D - 处理请求的时间,以毫秒为单位
  • %T - 处理请求的时间,以秒为单位
    另外,Access Log中也支持cookie,请求header,响应headers,Session或者其他在ServletRequest中的对象的信息。格式遵循apache语法:
1
2
3
4
5
%{xxx}i 请求headers的信息
%{xxx}o 响应headers的信息
%{xxx}c 请求cookie的信息
%{xxx}r xxx是ServletRequest的一个属性
%{xxx}s xxx是HttpSession的一个属性

common模式的pattern(即默认pattern参数)的格式为’%h %l %u %t “%r” %s %b’。

combined模式的pattern可以增加Referer和User-Agent headers的参数形式,每个参数用双引号包起来,引号中的内容还是上面列举的参数。比如”%{User-Agent}i”使其为”%{User-Agent}i“,即请求的User-Agent(客户端,浏览器)。

关于Common Log Format参考:http://baike.baidu.com/view/2948003.htm

配置普通日志格式

1
2
3
4
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs" prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t %r %s %b %{Referer}i %{User-Agent}i %D"
resolveHosts="false" />

日志访问实例

1
2
192.168.0.113 - - [11/Jul/2016:16:25:53 +0800] PUT /fontgenerate/ HTTP/1.1 200 37 - Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like G
ecko) Chrome/45.0.2454.101 Safari/537.36 1

将日志格式输出为json格式

1
2
3
4
5
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log." suffix=".json"
pattern="{&quot;client&quot;:&quot;%h&quot;, &quot;client user&quot;:&quot;%l&quot;, &quot;authenticated&quot;:&quot;%u&quot;, &quot;access time&quot;:&quot;%t&quot;, &quot;method&quot;:&quot;%r&quot;, &quot;status&quot;:&quot;%s&quot;, &quot;send bytes&quot;:&quot;%b&quot; , &quot;partner&quot;:&quot;%{Referer}i&quot;, &quot;Agent version&quot;:&quot;%{User-Agent}i&quot;, &quot;request_duration&quot;:&quot;%D&quot;}"
resolveHosts="false" />

访问日志结果:

1
2
3
4
5
6
7
8
9
10
11
12
{
"client": "192.168.0.13",
"client user": "-",
"authenticated": "-",
"access time": "[14/Sep/2016:11:03:33 +0800]",
"method": "GET /fontgenerate/?text=hello%E5%88%9D%E9%A1%B5&fontName=HYHLZTJ.ttf&type=Woff HTTP/1.1",
"status": "200",
"send bytes": "11572",
"partner": "http://192.168.0.226:8080/",
"Agent version": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.101 Safari/537.36",
"request_duration": "42"
}