Tomcat
部署Tomcat环境
环境准备
linux: CentOS 7.3
tomcat: 9.0.0.M21
jdk: 1.8.0_131
ip: 192.168.1.5
tomcat官方下载地址
http://tomcat.apache.org/download-90.cgi
下载tomcat
# cd /usr/local/src
# wget -c http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v9.0.0.M21/bin/apache-tomcat-9.0.0.M21.tar.gz
添加tomcat的用户并设置密码
# useradd -u 601 tomcat
# echo "tomcat" | passwd --stdin tomcat
解压tomcat的tar包
# tar -zxvf apache-tomcat-9.0.0.M21.tar.gz
移动tomcat到目录/usr/local下
# mv /usr/local/src/apache-tomcat-9.0.0.M21 /usr/local
最佳实践方式,软连接
# ln -sv /usr/local/apache-tomcat-9.0.0.M21/ /usr/local/tomcat
下载JDK的tar包(jdk-8u131-linux-x64.tar.gz)下载到到/usr/local/src目录中
官方下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
解压JDK的压缩包
# tar -zxvf jdk-8u131-linux-x64.tar.gz
移动JDK的目录到/usr/local下
# mv /usr/local/src/jdk1.8.0_131/ /usr/local
最佳实践方式,创建软连接
# ln -sv /usr/local/jdk1.8.0_131/ /usr/local/jdk
设置java所需要的运行环境
# cd /etc/profile.d/
# vim tomcat.sh
添加如下内容
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib/tools.jar
export TOMCAT_HOME=/usr/local/tomcat
让tomcat的配置脚本生效
# source /etc/profile.d/tomcat.sh
监测java的环境
# java -version
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
更改jdk及tomcat目录的属主属组
# chown -R tomcat:tomcat /usr/local/jdk/
# chown -R tomcat:tomcat /usr/local/tomcat/
切换到tomcat用户
# su -l tomcat
启动tomcat服务
/usr/local/tomcat/bin/startup.sh
tomcat的默认根路径(生产的代码)
/usr/local/tomcat/webapps
编辑tomcat的访问控制xml配置文件
# vim /usr/local/tomcat/conf/tomcat-users.xml
在配置文件中添加用户tomcat,并设置密码为1qazxsw2,这样就可以访问manager-gui和admin-gui的管理界面了
<role rolename="manager-gui" />
<role rolename="admin-gui" />
<user username="tomcat" password="1qazxsw2" roles="manager-gui,admin-gui" />
重启tomcat服务
# /usr/local/tomcat/bin/shutdown.sh
# /usr/local/tomcat/bin/startup.sh
这个时候如果是通过其他主机去访问tomcat的manager管理界面(为了安全考虑,默认是只允许主机访问),是无法使用的,我们需要再次修改一丢丢的内容
# vim /usr/local/tomcat/webapps/manager/META-INF/context.xml
修改allow的内容如下
allow="127.d+.d+.d+|::1|0:0:0:0:0:0:0:1|d+.d+.d+.d+"
浏览器可以去访问我们的tomcat服务的管理页面了
http://192.168.1.5:8080/manager/html
创建管理tomcat的启动关闭状态脚本
vim /usr/bin/tomcat.sh
添加如下内容
#!/bin/bash
TomcatPath=/usr/local/tomcat
usage() {
echo "Usage:$0 [start|stop|status|restart]"
}
start_tomcat(){
/usr/local/tomcat/bin/startup.sh
}
stop_tomcat() {
TomcatPid=$(ps -aux | grep 'java' | grep 'tomcat' | grep -v 'grep' | awk '{print $2}')
kill -9 $TomcatPid
sleep 5;
TomcatStat=$(ps -aux | grep 'java' | grep 'tomcat' | grep -v 'grep' | awk '{print $2}') >> /dev/null
if [ -z $TomcatStat ];then
echo -e " 33[31mtomcat stoping.. 33[0m"
else
kill -9 $TomcatStat
fi
cd $TomcatPath
rm -rf temp/*
rm -rf work/*
}
stat_tomcat() {
TomcatStat=$(ps -aux | grep 'java' | grep 'tomcat' | grep -v 'grep') >> /dev/null
if [ -z $TomcatStat ];then
echo -e " 33[31mtomcat stop.. 33[0m"
else
echo -e " 33[32mtomcat running... 33[0m"
fi
}
main(){
case $1 in
start)
start_tomcat;;
stop)
stop_tomcat;;
restart)
stop_tomcat && start_tomcat;;
status)
stat_tomcat;;
*)
usage;;
esac
}
main $1
更改脚本的属组属组并添加运行权限
# chown tomcat:tomcat /usr/bin/tomcat.sh
# chmod +x /usr/bin/tomcat.sh
测试下写的tomcat的脚本
# tomcat status
Tomcat的安全管理规范
1. telnet管理端口保护
8005为管理端口,可以通过telnet连接执行SHUTDOWN即可关闭服务,不安全,我们需要换一个其他人未知的端口并调整关闭命令,我们需要做调成
# vim /usr/local/tomcat/conf/server.xml
<Server port="8561" shutdown="dangerous">
2. ajp连接端口的保护,注释掉ajp
# vim /usr/local/tomcat/conf/server.xml
<!--Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /-->
Tomcat使用远程监测工具
windows下载并安装jdk,使用jconsole就可以监控tomcat的状态
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
修改tomcat服务端的配置
# vim /usr/local/tomcat/bin/catalina.sh
在第二行添加如下内容
CATALINA_OPTS="$CATALINA_OPTS -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=192.168.1.5"
利用jdk中的jconsole实现远程管理tomcat
使用jvisualvm监控tomcat
JVM原理及调优
-
什么是jvm?
虚拟机、字节码、跨平台
-
jvm结构
-
JVM运行时的数据区
- 程序计数器-------->线程私有
- Java虚拟机栈----->线程私有
- 本地方法栈-------->线程私有
- Java堆-------------->线程公用
- 方法区-------------->线程公用
-
jVM结构图
-
jvm内存分配
栈内存分配
1. 保存参数、局部变了、中间计算过程和其他数据,退出方法的时候,修改栈顶指针就可以把栈帧中的内容销毁 2. 栈的优点:存储速度比堆快,仅次于寄存器,栈数据可以共享 3. 栈的缺点:存在栈中的数据大小,生存期是在编译时候就确定的,导致其缺乏灵活性
堆内存分配
1. 堆的优点:动态分配内存大小,生存期不必实现告诉编译器,它是在运行期动态分配的,垃圾回收器会自动收走不再使用的空间区域 2. 堆的缺点:运行动态分配内存,在分配和销毁时都要占用时间,因此堆效率较低
-
jvm堆配置参数
1. -Xms初始堆大小 默认物理内存的1/64(<1GB) 2. -Xmx最大堆大小 默认物理内存的1/4(<1GB),实际中建议不大于4GB 3. 一般建议设置-Xms=-Xmx 好处是避免每次在gc后,调整堆的大小,减少系统内存分配开销 4. 整个堆大小=年轻代大小+年老代大小+持久化大小
-
jvm新生代(young generation)
1. 新生代=1个eden区+2个Survior区 2. -Xmn 年轻代大小(1.4or lator) -XX:NewSize,-XX:MaxNewSize(设置年轻代大小(for 1.3/1.4)) 默认值大小为整个堆的3/8 3. -XX:NewRatio 年轻代(包含Eden和两个Survivor区)与老年代的比值(除去持久化) Xms=Xmx并且设置了Xmn的情况下,该参数不需要设置 4. -XX:SurviorRatio Eden区与Survivor区的大小比值,设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10 5. 用来存放JVM刚分配的Java对象
-
jvm老年代(tenured greneration)
1. 老年代=整个堆-年轻代大小-持久化大小 2. 年轻代中经过垃圾回收没有回收掉的对象被复制到年老代 3. 老年代存储对象比年轻代年龄大的多,而且不发达对象(缓存) 4. 新建的对象也有可能直接进入老年代 4.1、大对象,可通过启动参数设置-XX:PretenureSizeThreshold=1024(单位为字节,默认为0)来代表超过多大时就不再新生代分配,而是直接在老年代分配 4.2、大的数组对象,切数组中无引用外部对象 5. 老年代大小无配置参数
-
java持久代(perm generation)
1. 持久代=整个堆-年轻代大小-老年代大小 2. -XX:PermSize -XX:MaxPermSize 设置持久代的大小,一般情况推荐把-XX:PermSize设置成XX:MaxPermSize的值为相同的值,因为永久代的调整也会导致堆内存需要触发fgc(Full GC) 3. 存放Class,Method元信息,其大小与项目的规模、类、方法的数量有关。一般设置为128M就够用,设置原则是预留30%的空间 4. 永久代的回收方式 4.1、常量池的常量,无用的类信息,常量的回收很简单,没有引用的就可以被回收 4.2、对无用的类进行回收,必须保证3点: 类的所有实例都已经被回收 加载类的ClassLoader已经被回收 类对象的Class对象没有被引用(既没有通过反射引用该类的方法)
-
jvm内存垃圾收集算法
1. 引用计数器 每个对象有一个引用计数器,新增一个引用时计数加1,引用释放时计数减1,技术为0时可以回收。此方法简单,无法解决对象相互循环引用的问题,还有一个问题是如何解决精准计数 2. 根搜索法 从GC Roots开始向下搜搜,搜索所走过的路径成为引用链,当一个对象到GC Roots对任何引用链相连时,则证明此对象不可用的,不可达对象 在Java语言中,GC Roots包含: 虚拟机栈中引用对象 方法区中类静态属性实时引用的对象 方法区中常量引用的对象 本地方法栈中JNI引用的对象 3. 复制算法(Copying) 复制算法采用从根结合扫描,并将存货对象复制到一块新的,没有使用过的空间中,这种算法当控件存货的对象比较少时,极为高效,但是带来的成本是需要一块内存交换空间用于进行对象的移动 注意: 此算法用于新生代内存回收,从E区回收到S0或者S1 4. 标记清除算法(Mark-Sweep) 标记-清除算法采用从根集合进行扫描,对存货的对象标记,标记完毕后,在扫描整个空间中未被标记的对象,进行回收,标记清楚算法不需要进行对象的移动,并且仅对不存货的对象进行处理,在存货对象比较多的情况下极为高效,但由于标记-清除算法会受不存活的对象,因此会造成内存碎片(适用于old区域) 5. 标记压缩压缩算法(Mark-Compac) 标记-整理算法采用标记-清除算法一样的方法进行对象的标记,但是在清除的时不同,在回收不存活的对象占用的空间后,会将所有的存活对象往左端的空间移动,并更新对应的指针,因此成本高,但是却解决了内存碎片的问题(old区域)
-
名词解释
1. 串行回收 GC单线程内存回收,会暂停所有用户线程 2. 并行回收 手机是指多个GC线程并行工作,蛋姿势用户线程是暂停的,所以,Serial是串行的,Parallel收集是并行的,而CMS手机是并发的 3. 并发回收 指用户线程与GC线程同时执行(不一定是并行,可能是交替,蛋总体上是在同时执行的),不需要停顿用户线程(其实在CMS中用户线程还是需要停顿的,只是非常的短暂,GC线程是在另一个CPU上执行)
-
CMS(并发标记清除)回收器
1. 标记-清除算法 同时它又是一个使用多线程并发回收的垃圾回收期 2. -XX:ParallelCMSThreads 手工设置CMS的线程数量,CMS默认启动的线程数为(ParallelCGThread+3)/4 3. -XX:+UseConcMarkSweepCG开启 使用过ParNew+CMS+Serial Old的收集器组合进行内存回收,Serial Old作为CMS出现"Concurrent Mode Failure"失败后的后背收集器使用 4. -XX:CMSInitiatingOccupancyFration 设置CMS收集器在老年代空间被使用多少后触发垃圾收集,默认为68%,仅在CMS收集器时有效,-XX:CMSInitiatingOccupancyFration=70 5. -XX:+UseCMSCompactAtFullCollection 用于CMS收集器会产生碎片,此参数设置在垃圾收集器后是否需要一次内存碎片整理过程,仅在CMS收集时有效 6. -XX:+CMSFullCGBeforeCompaction 设置CMS收集器在进行若干次垃圾收集后在进行一次内存碎片整理过程,通常与UseCMSCompactATFullCollection参数一起使用 7. -XX:CMSInitiatingPermOccupancyFraction 设置Perm Gen使用达到多少比率时触发,默认为92%