Tomcat解析、优化
一、Tomcat解析、优化
一、Java的组成部分
1、简述Java组成部分
- bin:tomcat的脚本文件,catalina.sh
- conf:tomcat的配置文件
- lib:存放的是tomcat自带的jar(java程序,class文件) jar存放的地方(jdk安装目录下lib、jre\lib、tomcat安装目录下lib、开发人员编写的应用程序下lib) 注意:jar版本冲突
- logs:存放tomcat日志,catalina.out日志(日志级别)
- tmp:tomcat临时目录
- webapps:存放tomcat自带的应用
- work:存放了tomcat运行时,web应用jsp页面转变为,java程序,和class的目录
2、配置文件
- server.xml:tomcat核心配置文件;定义tomcat提供服务的很多组件、这些组件属性的设定
- context.xml:每个webapp都有自己本身的配置,WBE-INF目录,
- web.xml:每个web应用被tomcat加载(jvm加载)时的参数配置
- tomcat-users.xml:用户认证账号配置文件
- logging.properties:日志相关的配置文件
- catalina.properties:java属性的配置文件,用于定于用于设定类加载器路径,以及一些jvm性能调整的相关参数
- catalina.policy:安全运行策略
1、server.xml组件:由Java类实现
顶级组件:Server(tomcat实例,,关闭tomcat,提供tomcat管理端。。。。。)
port:监听tomcat管理端口
shutdown:传递什么信号可以关闭tomcat实例
服务类组件:service 将连接器和引擎关联起来
tomcat运行在java,系统级服务
容器类组件:Engine(web server),Host,Context
连接器组件(Connector):使用java虚拟机向linux内核发起端口注册(绑定)请求,监听端口,接收用户请求
connectionTimeout:连接超时时长,单位是毫秒 keepAliveTimeout:长连接保持时长,15秒 单位是毫秒 maxSpareThreads:最大空闲线程 minSpareThreads:最小空闲线程 maxConnections:tomcat最多能并发处理的请求 acceptCount:每个tomcat线程,接收请求队列的长度,2 MaxThreads:tomcat启动最大线程数
被嵌套类组件:valve(过滤器),realm(安全域)
*/ <Server> 代表一个tomcat实例(tomcat进程) <Service>: <Connector>:代表和客户程序实际交互的组件,负责接收客户请求,以及向客户返回相应结果 <engine:处理在同一个<Service>中所有Connector组件接收的客户请求 <Host>:虚拟主机 <Context>:web应用 /* <Server> <Service> <engine> </engine> <Connector> </Connector> </Service> </Server>
二、部署环境
下载所需的JDK和Jmeter
1、Linux上安装JDK8和jmeter5.0
cd /opt/soft
#上传所需安装包 apache-jmeter-5.0.zip jdk-8u192-linux-x64.tar
tar -xf jdk-8u192-linux-x64.tar
ln -s jdk1.8.0_192/ /opt/soft/java
unzip apache-jmeter-5.0.zip
#创建环境变量
#编辑/etc/profile
export JAVA_HOME=/usr/java/jdk1.8.0_192
export CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib
#jmeter
export JMETER=/opt/ytd_soft/apache-jmeter-5.0
export CLASSPATH=$JMETER/lib/ext/ApacheJMeter_core.jar:$JMETER/lib/jorphan.jar:$CLASSPATH
export PATH=$JMETER/bin/:$PATH
#生效配置文件
source /etc/profile
#验证
java -version
jmeter --version
2、安装Linux图形化包
Linux环境若没有安装图形化包会报下面的错误
# jmeter
================================================================================
Don't use GUI mode for load testing !, only for Test creation and Test debugging.
For load testing, use NON GUI Mode:
jmeter -n -t [jmx file] -l [results file] -e -o [Path to web report folder]
& increase Java Heap to meet your test requirements:
Modify current env variable HEAP="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m" in the jmeter batch file
Check : https://jmeter.apache.org/usermanual/best-practices.html
================================================================================
An error occurred:
No X11 DISPLAY variable was set, but this program performed an operation which requires it.
安装所需的包(yum intall xorg-x11-xauth)
yum install xorg-xll-xauth xorg-x11-server-utils xorg-x11-server-Xnest libXtst -y
验证(若还报错,可以重启一下机器,在进行测试)
# jmeter
3、jmeter介绍
1、bin底下脚本介绍
/data/apache-jmeter-3.1/bin目录下的脚本:jmeter脚本文件,应该在绝大多数linux/UNIX系统上运行
jmeter:运行JMeter(默认GUI模式)。定义了一些JVM设置,但并不是对所有JVM都生效
jmeter-server:以服务器模式启动JMeter(通过合适的参数来调用jmeter脚本)。
jmeter.sh:没有指定JVM选项的非常基础的jmeter脚本
mirror-server.sh:在非GUI模式下启动JMeter镜像服务器
shutdown.sh:关闭一个非GUI实例(优雅的)
stoptest.sh:停止一个非GUI实例(中断式的)
使用一个产品的原则:使用路径(用户使用路径)
功能繁多,会导致使用路径非常多,很多刚接触的用户经常会迷路
先研究和掌握最核心的一条用户路径
JMeter(怎么对一个web服务进行压力测试)
2、JMeter常用术语
1、采样器(Samplers):采样器是JMeter测试脚本的基础单元用户可以用它来向服务器发出一个特定的请求,采样器会在超时前等待服务器的响应。
2、逻辑控制器(Logic Controllers):用户通过逻辑控制器来控制JMeter测试脚本的执行顺序,以便测试能够按照用户期望的顺序和逻辑执行
3、监听器(Listeners):监听器被用来收集测试结果信息,并以用户指定的方式加以展示
4、配置元件(Configuration Elements):配置元件被用来设置一些JMeter测试脚本公用的信息
5、断言(Assertions):断言被用来验证服务器实际返回的信息与用于期望的情况是否相符
6、定时器(Timers):定时器被用来保存JMeter测试脚本与时间相关的一些信息,例如思考时间(Think Time)
7、前置处理器(Pre-Processos):在前置处理器的作用范围内,任何采样被执行前,都要先执行前置处理器
8、后置处理器(Post-Processors):在后置处理器的作用范围内,任何采样器被执行后,都要执行对应的后置处理器
9、测试计划(Test Plan):测试计划是JMeter测试脚本的根节点,关于整个测试脚本的一些基础设置,可以在测试计划中设定,例如用户定义变量
10、线程组(Thread Group):线程组定义了一个虚拟用户池,其中每一个虚拟用户都使用同样的测试脚本
11、工作台(WorkBench):工作台被用来保存暂时不使用的测试元素,当测试人员保存测试计划时,工作台中的内容不会被一起保存
3、JMeter测试结果字段的意义
Label:定义HTTP请求名称
Samples:表示这次测试中一共发出了多少个请求
Average:平均响应时长---默认情况下是单个Request的平均响应时长,当使用Transaction Controller时,也可以以Transaction为单位显示平均响应时长
Median:中位数,也就是50%用户的响应时长
90%Line:90%用户的响应时长
Min:访问页面的最小响应时长
Max:访问页面的最大响应时长
Error%:错误请求的数量/请求的总数
Throughput:默认情况下表示每秒完成的请求数(Request per Second),当使用了Transaction Controller时,也可以表示类似LoadRunner的Transaction per Second数。
KB/Sec:每秒从服务器端接收到的数据量
4、建立测试计划
线程组:
HTTP采样器的配置元件:
采样器:/index.html
/index.php
监听器
三、Tomcat优化
1、server.xml主要优化参数
基准、压力测试和性能测试
jmeter(性能测试)、ab(基准测试,压力测试) ab:httpd服务自带的一个工具(apache) yum install httpd-tools ab参数: -c:模拟用户数(启动多个进程或者是线程发起请求) -n:总共要发起的并发请求数 -k:禁止Keep-Alive
ab -k -c 1 -n 2 http://www.baidu.com/index.html
打印日志,并分析
for i in {1..10000}; do netstat -n|awk '/^tcp/ {++S[$NF]} END{for(a in S) print a,S[a]}' >>/tmp/tcp.log; free -m >>mem.log; vmstat >>cpu.log; sleep 1; done
mssssaxThreads尽量设置的小一点,当tomcat的线程数过大时,cpu资源都会浪费在tomcat线程调度上。线程调度消耗的cpu资源其实就是浪费的cpu资源,当cpu核心数<线程数,其实就会产生线程调度,(合理控制)
maxThreads:tomcat能够启动的最大线程数 100 处理用户请求的线程
minSpaceThreads:tomcat初始化的线程池大小。
acceptCount:tomcat每个线程维护的最大队列长度
maxConnections:tomcat能够允许多少个客户tcp链接
2、数据库连接池配置
1、主要优化参数
#初始化连接:连接池启动时创建的初始化连接数量 initialSize=10 #连接池的最大数据库连接数。设为0表示无限制 maxActive=50 #最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被释放。设为0表示无限制 maxIdle=10 #最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接 minIdle=5 #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制 maxWait=1000 #超过removeAbandonedTimeout时间后,是否进 行没用连接(废弃)的回收(默认为false,调整为true) removeAbandoned=true #超过时间限制,回收没有用(废弃)的连接(默认为 300秒,调整为180) removeAbandonedTimeout=180
2、配置方法
方法一:在Tomcat的conf/context.xml中配置
<!--配置mysql数据库的连接池, 需要做的额外步骤是将mysql的Java驱动类放到tomcat的lib目录下 maxIdle 连接池中最多可空闲maxIdle个连接 minIdle 连接池中最少空闲maxIdle个连接 initialSize 初始化连接数目 maxWait 连接池中连接用完时,新的请求等待时间,毫秒 username 数据库用户名 password 数据库密码 --> <Resource name="jdbc/mysqlds" auth="Container" type="javax.sql.DataSource" username="root" password="root" maxIdle="30" maxWait="10000" maxActive="100" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/db_blog" /> </Context> 配置好后需要注意的两个步骤 1.将对应数据库的驱动类放到tomcat的lib目录下 2.重新启动tomcat服务器,让配置生效
方法二:在Tomcat的conf/server.xml中配置
打开tomcat的conf/server.xml文件,找到<GlobalNamingResources></GlobalNamingResources>节点,默认的内容如下 <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> 在该节点中加入相关的池配置信息,如下 <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" /> <!--配置mysql数据库的连接池, 需要做的额外步骤是将mysql的Java驱动类放到tomcat的lib目录下 --> <Resource name="jdbc/mysqlds" auth="Container" type="javax.sql.DataSource" username="root" password="root" maxIdle="30" maxWait="10000" maxActive="100" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/db_blog" /> </GlobalNamingResources> 在tomcat的conf/context.xml文件中的<Context></Context>节点中加入如下内容 <ResourceLink name="jdbc/mysqlds" global="jdbc/mysqlds" type="javax.sql.DataSource"/> 然后在web项目中的WEB-INF目录下的web.xml中配置 <resource-ref> <description>mysql Connection</description> <!-- 参考数据源名字,同Tomcat中配置的Resource节点中name属性值"jdbc/mysqlds"一致 --> <res-ref-name>jdbc/mysqlds</res-ref-name> <!-- 资源类型 --> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> <res-sharing-scope>Shareable</res-sharing-scope> </resource-ref> 同样配置好后,需要重新启动服务器,让配置生效.
方法三:web应用中中配置方法一
在Web项目中的META-INF目录下新建一个文件context.xml,写入配置 注意:是META-INF目录下,不是WEB-INF目录下 <?xml version='1.0' encoding='utf-8'?> <Context> <Resource name="jdbc/mysqlds" auth="Container" type="javax.sql.DataSource" username="root" password="root" maxIdle="30" maxWait="10000" maxActive="100" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/db_blog" logAbandoned="true" /> </Context>
3、mysql jdbc url参数详解:
user 数据库用户名,用于连接数据库 所有版本 password 用户密码(用于连接数据库) 所有版本 useUnicode 是否使用Unicode字符集,如果参数characterEncoding设置为gb2312或gbk,本参数值必须设置为true false characterEncoding 当useUnicode设置为true时,指定字符编码。比如可设置为gb2312或gbk,utf8 false autoReconnect 当数据库连接异常中断时,是否自动重新连接? false autoReconnectForPools 是否使用针对数据库连接池的重连策略 false failOverReadOnly 自动重连成功后,连接是否设置为只读? true maxReconnectsautoReconnect 设置为true时,重试连接的次数 3 initialTimeoutautoReconnect设置为true时,两次重连之间的时间间隔,单位:秒 connectTimeout 和数据库服务器建立socket连接时的超时,单位:毫秒。 0表示永不超时,适用于JDK 1.4及更高版本 socketTimeoutsocket操作(读写)超时,单位:毫秒。 0表示永不超时
范例
jdbc:mysql://localhost:3306/test?user=root&password=&useUnicode=true&characterEncoding=gbk&autoReconnect=true&failOverReadOnly=false
3、JVM优化
-Xms:设置初始化堆大小 -Xmx:设置堆最大可使用空间 -Xss128k:虚拟机栈和本地方法栈溢出 -XX:PermSize=10M -XX:MaxPermSize=10M :运行时常量池的内存溢出
范例如下
export GC_LOG_DIR=/opt/logs/gc # 此处修改为规定的路径 export HEAPDUMP_DIR=/opt/logs/gc # 此处修改为规定的路径 mkdir -p ${GC_LOG_DIR} mkdir -p ${HEAPDUMP_DIR} jdk_verbose_version=`java -version 2>&1 | grep version | awk -F"\"" '{print $2}'` echo "JDK version: ${jdk_verbose_version}" jdk_major_version=`java -version 2>&1 | grep version | awk -F"." '{print $2}'` if [ ${jdk_major_version} -gt 7 ] then # jdk7 之后的版本 JAVA_OPTS="${JAVA_OPTS} -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=384m" else # jdk7 以及之前的版本 JAVA_OPTS="${JAVA_OPTS} -XX:PermSize=256M -XX:MaxPermSize=384M" JAVA_OPTS="${JAVA_OPTS} -XX:+UseConcMarkSweepGC -XX:CMSMaxAbortablePrecleanTime=5000" fi JAVA_OPTS="${JAVA_OPTS} -Xms2g -Xmx4g" JAVA_OPTS="${JAVA_OPTS} -Xloggc:${GC_LOG_DIR}/gc.log_$(date +%F) -XX:+PrintGCDetails -XX:+PrintGCDateStamps" JAVA_OPTS="${JAVA_OPTS} -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${HEAPDUMP_DIR}/heapdump_$(date +%m-%d_%H:%M:%S).hprof" JAVA_OPTS="${JAVA_OPTS} -Dfile.encoding=UTF-8" export JAVA_OPTS