目录
[2.Tomcat 的核心组件](#2.Tomcat 的核心组件)
[3.Tomcat 功能组件结构](#3.Tomcat 功能组件结构)
[2.安装 JDK](#2.安装 JDK)
[3.配置 JDK 环境变量](#3.配置 JDK 环境变量)
[四、Tomcat 虚拟主机配置](#四、Tomcat 虚拟主机配置)
[1.安装 JDK](#1.安装 JDK)
[3.配置 Tomcat 环境变量](#3.配置 Tomcat 环境变量)
[4.修改 Tomcat 实例配置文件](#4.修改 Tomcat 实例配置文件)
一、Tomcat概述
1.Tomcat定义
Tomcat 是由 Apache 软件基金会的 Jakarta 项目开发的一款开源的、免费的 Web 应用服务器,主要用于运行 Java Servlet 和 JSP(Java Server Pages),并且支持 Java EE 规范中的一些核心组件
Tomcat 作为一个轻量级的应用服务器,广泛应用于中小型系统,尤其是在并发访问量不大的场合。尽管 Tomcat 能处理 HTML 页面,但其处理静态 HTML 的能力不及专门的 Web 服务器如 Apache 或 Nginx,因此 Tomcat 通常在后端作为 Servlet 和 JSP 容器运行
2.Tomcat 的核心组件
Web 容器
功能:负责处理和管理 Web 应用服务
作用:封装和管理 Web 应用中的一组文件,提供集中化管理。通过 HTTP(S)协议访问 Web页面
示例:提供静态和动态网页服务,动态页面可以与用户进行交互
Servlet 容器(Catalina)
功能:处理 Servlet 代码,执行后端的业务逻辑
作用:接收客户端请求,执行 Servlet 中的 Java 代码,生成响应并返回给客户端
示例:处理动态 Web 请求,如用户提交表单后进行数据处理
JSP 容器
功能:将 JSP 页面翻译成 Servlet 代码
作用:将JSP(JavaServer Pages)中的动态内容转换为可执行的 Servlet 代码,从而生成动态 Web 页面
示例:index.jsp用于 Tomcat 服务器处理动态内容并与后端数据进行交豆,类似于 PHP的index.php
3.Tomcat 功能组件结构
Tomcat 作为一款轻量级的 Java Web 应用服务器,其核心功能组件包括 Connector(连接器)和 Container(容器)。这两个组件相辅相成,共同构成了 Tomcat 的基本 Web 服务 Service。每个 Tomcat 服务器可以管理多个 Service,各 Service 之间相互独立
Connector
作用:负责接收和响应外部请求
功能:Tomcat 的交通枢纽,监听网络端口,接收客户端请求。将请求传递给容器(Container)处理,并将处理后的响应返回给客户端
Container
作用:负责处理业务逻辑
组成:内部包含以下四个容器
Engine:处理请求,并将结果传递给 Host
Host:表示虚拟主机,管理多个 Web 应用(Context)
Context:代表具体的 Web 应用,处理实际的请求和响应
Wrapper:封装 Servlet 组件,负责调用和管理 Servlet 的生命周期
Service
作用:提供 Web 服务
功能:包含 Connector 和 Container 这两个核心组件。Tomcat 可以管理多个 Service,每个 Service 相互独立
二、Tomcat请求处理过程
1.客户端发送请求
客户端通过浏览器或其他客户端工具,向 Tomcat 服务器发送 HTTP 请求
2.Connector 接收请求
监听端口:Tomcat 的 connector 组件监听预先配置的端口(如8080)
解析请求:当请求到达时,connector接收并解析请求的基本信息,包括请求方法(如 GETPOST)、URL、头部信息等
创建Request和Response对象:connector创建代表请求的Request对象和代表响应的Response对象,这些对象将携带请求数据和响应数据
3.Connector 传递请求到 Container
选择适当的 Container:根据请求的 URL和上下文路径,connector将请求传递给合适的container进行处理
分配线程:connector从线程池中分配一个工作线程,来处理该请求4.Container 处理请求
Engine 处理:Engine是处理请求的顶层容器,负青将请求路由到适当的Host
Host 处理:Host代表虚拟主机,确定请求要处理的具体 context (即 Web 应用)
Context 处理:context代表具体的 Web 应用,确定请求需要调用的servlet
Wrapper 调用 Servlet:wrapper封装了特定的servlet,它负责调用 servlet 的 service()方法处理请求
servlet根据请求的数据执行相应的业务逻辑,生成响应内容
5.Servlet 生成响应servlet处理完成后,将生成的响应数据(如HTML页面、JSON数据等)写入到Response对象中
- Container 返回响应
回传到 Connector:container将处理完的 Response 对象返回给 connector
发送响应:connector 将 Response 对象中的数据通过网络发送回客户端
7.客户端接收响应客户端接收到 Tomcat 返回的响应数据,并根据响应内容显示或处理
8.结束请求处理
释放资源:Tomcat 清理请求相关的资源,关闭工作线程,将线程返回到线程池中,以便处理新的请求
三、Tomcat安装部署
tomcat官网网站下载:https://tomcat.apache.org/download-90.cgi
JDK官方下载:https://www.oracle.com/java/technologies/downloads/#java22
在部署 Tomcat 之前必须安装好 jdk,因为 jdk 是 Tomcat 运行的必要环境
1.关闭防火墙和临时防护
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
2.安装 JDK
cd /opt
rpm -qpl jdk-8u201-linux-x64.rpm
rpm -ivh jdk-8u201-linux-x64.rpm
java -version
3.配置 JDK 环境变量
编辑/etc/profile.d/java.sh文件
vim /etc/profile.d/java.sh
添加以下内容
export JAVA_HOME=/usr/java/jdk1.8.0_201-amd64
export CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar
export PATH=$JAVA_HOME/bin:$PATH
使环境变量生效
source /etc/profile.d/java.sh
java -version
4.编写和运行Java程序示例
编写Hello.java
vim Hello.java
public class Hello {
public static void main(String[] args){
System.out.println("Hello world!");
}
}
编译和运行Java程序
javac Hello.java
java Hello
5.安装和启动Tomcat
解压Tomcat并移动到/usr/local
cd /opt
tar zxvf apache-tomcat-9.0.16.tar.gz
mv apache-tomcat-9.0.16 /usr/local/tomcat
启动Tomcat
后台启动
/usr/local/tomcat/bin/startup.sh
前台启动
/usr/local/tomcat/bin/catalina.sh run
检查Tomcat是否在运行
netstat -natp | grep 8080
访问Tomcat默认主页
浏览器访问:http://172.16.58.10:8080
6.配置Tomcat为系统服务
创建Tomcat用户
useradd -s /sbin/nologin tomcat
修改Tomcat目录权限
chown tomcat:tomcat /usr/local/tomcat -R
创建Tomcat服务文件
cat > /usr/lib/systemd/system/tomcat.service <<EOF
[Unit]
Description=Tomcat
After=syslog.target network.target
[Service]
Type=forking
ExecStart=/usr/local/tomcat/bin/startup.sh
ExecStop=/usr/local/tomcat/bin/shutdown.sh
RestartSec=3
PrivateTmp=true
User=tomcat
Group=tomcat
[Install]
WantedBy=multi-user.target
EOF
重新加载系统服务并启动Tomcat
systemctl daemon-reload
systemctl start tomcat
检查Tomcat服务是否启动
ss -ntap | grep 8080
7.优化Tomcat启动速度
第一次启动Tomcat可能会发现Tomcat启动很慢,默认情况下可能会需要几十秒,可以修改JDK的配置文件来加快启动速度
修改java.security文件
vim /usr/java/jdk1.8.0_201-amd64/jre/lib/security/java.security
在配置文件找到117行
securerandom.source=file:/dev/urandom
重启Tomcat
/usr/local/tomcat/bin/shutdown.sh
/usr/local/tomcat/bin/startup.sh
/dev/urandom是/dev/random的非阻塞版本。/dev/random 依赖系统中断,因此在系统中断不足时会阻塞,导致进程等待。而/dev/urandom不依赖系统中断,不会阻塞进程,但随机性较低。如果应用对安全性要求较高,应使用/dev/random
8.Tomcat主要目录说明
ll /usr/local/tomcat/
bin
功能:存放启动和关闭Tomcat的脚本文件
常用文件:
catalina.sh:Tomcat的主要启动脚本,通常用于启动、停止、重启Tomcat
startup.sh:用于启动Tomcat
shutdown.sh:用于关闭Tomcat
conf
功能:存放Tomcat服务器的各种配置文件
常用文件:
server.xml:Tomcat的主配置文件,包含Service、Connector、Engine、Realm、Valve和Host等主要组件的配置
context.xml:所有Host的默认配置信息
tomcat-users.xml:用于配置Realm认证的角色、用户和密码等信息。Tomcat的管理工具如manager默认使用此文件来管理用户和角色
web.xml:遵循Servlet规范的配置文件,配置Servlet以及为所有Web应用程序提供默认的配置信息,如MIME映射等
lib功能:存放Tomcat运行所需的库文件 (jar包)
说明:一般不需要修改,除非需要连接第三方服务(如Redis),则需添加相应的jar包
logs功能:存放Tomcat运行时产生的日志文件
说明:包含Tomcat的运行日志、错误日志等
temp功能:存放Tomcat运行时产生的临时文件
说明:包括临时缓存文件等
webapps功能:存放Tomcat默认的Web应用部署目录
说明:这是Tomcat的默认应用目录,你可以在此目录下部署和管理Web应用
work功能:存放Tomcat工作时产生的文件
说明:包含JSP编译后生成的class文件,通常在清除Tomcat缓存时需要操作此目录
src功能:存放Tomcat的源代码
说明:通常用于开发和调试,不是运行时必需
doc功能:存放Tomcat的文档
说明:包含有关Tomcat的文档和使用说明
四、Tomcat 虚拟主机配置
当需要在同一台服务器上运行多个Tomcat 项目时,可以使用Tomcat的虚拟主机功能来管理多个域名访问不同的项目内容
1.创建项目目录和文件
mkdir /usr/local/tomcat/webapps/kgc
mkdir /usr/local/tomcat/webapps/benet
echo "This is kgc page!" > /usr/local/tomcat/webapps/kgc/index.jsp
echo "This is benet page!" > /usr/local/tomcat/webapps/benet/index.jsp
2.修改Tomcat主配置文件server.xml
编辑server.xml文件
vim /usr/local/tomcat/conf/server.xml
在文件中的<Engine>标签内的适当位置(165行前)插入一下配置
<Host name="www.kgc.com" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context docBase="/usr/local/tomcat/webapps/kgc" path="" reloadable="true" />
</Host>
<Host name="www.benet.com" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context docBase="/usr/local/tomcat/webapps/benet" path="" reloadable="true" />
</Host>
3.Tomcat配置项说明
appBase
功能:定义Tomcat的应用程序工作目录,即存放Web应用程序的目录
默认值:相对路径为webapps,绝对路径通常为/usr/local/tomcat/webapps
作用:指定Tomcat从哪里加载和部署Web应用程序
unpackWARs功能:决定在部署Web应用程序时是否对WAR格式的归档文件进行展开(解压)
默认值:true,表示Tomcat会自动解压WAR文件
作用:如果设置为true,Tomcat会将WAR文件解压缩为一个目录结构,这样可以直接查看和修改应用程序文件
autoDeploy功能:决定在Tomcat运行状态时,放置于appBase目录中的应用程序文件是否自动部署
默认值:true,表示Tomcat会自动检测和部署新的或更新的应用程序
作用:允许在Tomcat运行时自动部署新的应用程序或更新已有应用程序,无需手动重启Tomcat
xmlValidation功能:决定是否对XML文件执行有效性检验
作用:启用后,Tomcat会对Web应用程序中的XML文件(如web.xml)进行DTD或XSD的校验,以确保文件格式和内容的正确性
xmlNamespaceAware功能:决定是否启用XML命名空间支持
作用:如果设置为true,并且xmlvalidation也为true,则Tomcat会在执行XML文件的有效性检验时考虑命名空间。这对使用命名空间的XML文件(如复杂的web.xml文件)尤其重要
docBase功能:指定相应Web应用程序的存放位置
作用:可以使用相对路径或绝对路径。相对路径是相对于该Context所属Host中appBase定义的路径。docBase通常用于指定非标准appBase目录下的应用程序位置
path功能:定义相对于Web服务器根路径的URl(Uniform Resource ldentifier)
作用:如果设置为空' "" '则表示该Web应用程序的根路径是'/',即通过服务器的根URL访问此应用程序。例如path="/myapp",表示应用程序通过http://localhost:8080/myapp访问
reloadable功能:决定是否允许重新加载此Context相关的Web应用程序的类
默认值:false,表示Tomcat不会自动重新加载类文件
作用:如果设置为true,在检测到Web应用程序的类文件发生变化时,Tomcat会自动重新加载应用程序。此功能在开发环境中非常有用,但在生产环境中应谨慎使用,因为频繁的重载可能会导致性能问题
4.启动Tomcat服务
/usr/local/tomcat/bin/shutdown.sh //关闭 Tomcat
/usr/local/tomcat/bin/startup.sh //启动 Tomcat
5.客户端浏览器访问验证
更新/etc/host文件
echo "192.168.10.23 www.kgc.com www.benet.com" >> /etc/hosts
在浏览器中访问以下地址
访问 http://www.kgc.com:8080/ 页面应显示 "This is kgc page!"
访间 http://www.benet.com:8080/ 页面应显示 "This is benet page!"
五、Tomcat优化
Tomcat默认安装下的缺省配置并不适合生产环境,它可能会频繁出现假死现象需要重启,只有通过不断压测优化才能让它最高效率稳定的运行。优化主要包括三方面,分别为操作系统优化(内核参数优化),Tomcat配置文件参数优化,Java虚拟机(JVM)调优
1.Tomcat配置文件参数优化
redirectPort
描述:当连接器支持的协议是HTTP,且接收到HTTPS请求时,转发至该端口
用途:用于处理HTTP到HTTPS的重定向
maxThreads描述:Tomcat可以创建的最大线程数,表示支持的最大并发连接数。默认值为200
用途:控制Tomcat的线程池大小,影响并发处理能力
minSpareThreads描述:Tomcat启动时初始化的线程数,表示即使没有请求也会保留这些线程。默认值为10
用途:确保Tomcat在启动时有一定数量的空闲线程,减少初始请求的延迟
maxSpareThreads描述:最大备用线程数,一旦创建的线程数超过此值,Tomcat将关闭不再需要的线程。默认
值为-1(无限制)
用途:控制线程池中的最大空闲线程数,优化资源使用
URIEncoding描述:指定Tomcat容器的URL编码格式
用途:设置URL的编码格式,以支持不同的字符集
connnectionTimeout描述:网络连接超时,单位为秒,设置为0表示永不超时,通常默认值为20000秒(20秒)
用途:控制连接超时的时长,防止连接长时间占用资源
enableLookups描述:是否进行域名反查,以返回远程主机的主机名。取值为true或false,默认值为false
用途:提高处理能力,通常设置为false以避免反向解析带来的额外开销
disableUploadTimeout描述:是否在文件上传时使用超时机制。应设置为true
用途:避免上传文件时长时间占用连接
connectionUploadTimeout描述:上传超时时间,用于调整文件上传的超时时长。与disableUploadTimeout一起使用
用途:设置上传文件的超时时间,以适应不同的业务需求
acceptCount描述:当所有可用线程被占用时,允许的最大连接请求队列长度。超过此长度的请求将被拒
绝。默认值为100
用途:控制请求队列的长度,避免服务器过载
compression描述:是否对响应数据进行GZIP压缩。取值包括off(禁止压缩)、on(允许压缩)、force(强制压缩)。默认值为off
用途:减少页面数据大小,节省带宽
compressionMinSize描述:只有当响应报文大小大于此值时才会进行压缩。默认值为2048字节
用途:优化压缩性能,避免对小数据进行压缩
compressableMimeType描述:指定哪些类型的文件会进行数据压缩
用途:控制哪些MIME类型的响应数据会被压缩
noCompressionUserAgents描述:对于以下浏览器,不启用压缩,如"gozilla,traviata"
用途:避免某些浏览器无法正确处理压缩数据
2.配置文件
编辑sever.xml文件
vim /usr/local/tomcat/conf/server.xml
在<Connector>标签中添加或修改
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
minSpareThreads="50"
enableLookups="false"
disableUploadTimeout="true"
acceptCount="300"
maxThreads="500"
URIEncoding="UTF-8"
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,image/gif,image/jpeg,image/png"/>
3.Java虚拟机(JVM)调优
Tomcat 是一个运行在JVM上的Java 程序,其启动命令行中的优化参数主要涉及JVM的调优尤其是GC(垃圾回收)的优化。由于GC会导致程序运行中断,选择合适的GC策略并调整 JVM和GC参数,可以减少由于GC导致的中断,从而提高Java程序的运行效率
不同类型的程序(如 Web 和 GUI 程序)对停顿的容忍度不同,因此需要不同的GC策略。此外,不同机器的配置(如CPU数量、内存大小)也影响GC的选择和调优。因此,GC调优是一个复杂的过程,需要根据具体应用场景和硬件配置进行定制
server:在生产环境中运行Tomcat时必须第一个添加的参数,它确保后续参数有效Xms:表示Java初始化堆的大小,Xms与Xmx设成一样的值,避免JVM反复重新申请内存,导致性能大起大落,默认值为物理内存的1/64,默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到 -Xmx的最大限制
Xmx:表示最大Java堆大小,当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃,因此一般建议堆的最大值设置为物理内存的最大值的 50%
XX:NewSize:设置新生代内存大小
XX:MaxNewSize:设置最大新生代内存大小
XX:PermSize:设置持久代内存大小
XX:MaxPermSize:设置最大值持久代内存大小,永久代不属于堆内存,堆内存只包含新生代和老年代
XX:+AggressiveOpts:作用如其名(aggressive),若启用这个参数,则每当JDK版本升级时,JVM都会使用最新加入的优化技术(如果有的话)
XX:+UseBiasedLocking:启用一个优化了的线程锁,要知道在appserver,每个http请求就是一个线程,有的请求短有的请求长,就会有请求排队的现象,甚至还会出现线程阻塞,这个优化了的线程锁使得appserver内对线程处理自动进行最优调配
XX:+DisableExplicitGC:在程序代码中不允许有显示的调用"System.gc()"。每次在操作结束时手动调用System.gc() 一下,付出的代价就是系统响应时间严重降低,就和关于Xms,Xmx 里的原理一样,这样去调用GC会导致系统的JVM大起大落
XX:+UseParNewGC:对新生代采用多线程并行回收,这样收得快。需要注意的是在最新 JVM版本中,当使用 XX:+UseConcMarkSweepGC时,XX:UseParNewGC会自动开启。因此,如果年轻代的并行GC不想开启,可以通过设置XX:-UseParNewGC来关掉
XX:MaxTenuringThreshold:设置垃圾最大年龄。如果设置为 0 的话,则新生代对象不经过 Survivor区,直接进入老年代。对于老年代比较多的应用(需要大量常驻内存的应用),可以提高效率。如果将此值设置为一 个较大值,则新生代对象会在Survivor区进行多次复制,这样可以增加对象在新生代的存活时间,增加在新生代即被回收的概率,减少Full GC的频率,这样做可以在某种程度上提高服务稳定性。该参数只有在串行GC时才有效,这个值的设置是根据本地的jprofiler监控后得到的一个理想的值,不能一概而论原搬照抄
XX:+CMSParallelRemarkEnabled:在使用UseParNewGC的情况下,尽量减少mark的时间
XX:+UseCMSCompactAtFullCollection:在使用concurrent gc的情 况 下 , 防 止memoryfragmention,对 live object 进行整理,使 memory 碎片减少
XX:LargePageSizeInBytes:指定Java heap的分页页面大小,内存页的大小不可设置过大, 会影响 Perm 的大小
XX:+UseFastAccessorMethods:使用get,set方法转成本地代码,原始类型的快速优化
XX:+UseCMSInitiatingOccupancyOnly:只有在 oldgeneration 在使用了初始化的比例后 concurrent collector 启动收集
Duser.timezone=Asia/Shanghai:设置用户所在时区Djava.awt.headless=true:这个参数一般我们都是放在最后使用。有时我们会在我们的 J2EE工程中使用一些图表工具,如:jfreechart,用于在Web网页输出 GIF/JPG等流,在 Windows 环境下,一般我们的 app server 在输出图形时不会碰到什么问题,但是在 Linux/Unix 环境下经常会碰到一个 exception 导致你在 Windows 开发环境下图片正常显示,可是在 Linux/Unix 下却显示不出来,因此加上这个参数以免避这样的情况出现
Xmn:新生代的内存空间大小,注意:此处的大小是(eden+ 2 survivor space)。与 jmap-heap 中显示的 New gen 是不同的。整个堆大小 = 新生代大小 + 老生代大小 + 永久代大小。在保证堆大小不变的情况下,增大新生代后,将会减小老生代大小。此值对系统性能影响较大,Sun 官方推荐配置为整个堆的 3/8
XX:CMSInitiatingOccupancyFraction:当堆满之后,并行收集器便开始进行垃圾收集。例如,当没有足够的空间来容纳新分配或提升的对象。对于 CMS 收集器,长时间等待是不可取的,因为在并发垃圾收集期间应用持续在运行(并且分配对象)。因此,为了在应用程序使用完内存之前完成垃圾收集周期,CMS 收集器要比并行收集器更先启动。因为不同的应用会有不同对象分配模式,JVM 会收集实际的对象分配(和释放)的运行时数据,并且分析这些数据,来决定什么时候启动一次 CMS 垃圾收集周期。这个参数设置有很大技巧 , 基本上 满足(Xmx-Xmn)*(100-CMSInitiatingOccupancyFraction)/100 >= Xmn 就 不 会 出 现promotion failed。例如在应用中 Xmx 是 6000,Xmn 是 512,那么 Xmx-Xmn 是 5488M,也就是老年代有 5488M,CMSInitiatingOccupancyFraction=90 说明老年代到 90%满的时候开始执行对老年代的并发垃圾回收(CMS),这时还 剩 10%的空间是5488*10% = 548M,所以即使 Xmn(也就是新生代共 512M)里所有对象都搬到老年代里,548M 的空间也足够了,所以只要满足上面的公式,就不会出现垃圾回收时的promotion failed,因此这个参数的设置必须与 Xmn 关联在一起
XX:+CMSIncrementalMode:该标志将开启 CMS 收集器的增量模式。增量模式经常暂停 CMS 过程,以便对应用程序线程作出完全的让步。因此,收集器将花更长的时间完成整个收集周期。因此,只有通过测试后发现正常 CMS 周期对应用程序线程干扰太大时,才应该使用增量模式。由于现代服务器有足够的处理器来适应并发的垃圾收集,所以这种情况发生得很少,用于但 CPU 情况
XX:NewRatio:年轻代(包括 Eden 和两个 Survivor 区)与年老代的比值(除去持久代),-XX:NewRatio=4 表示年轻代与年老代所占比值为 1:4,年轻代占整个堆栈的1/5,Xms=Xmx 并且设置了 Xmn 的情况下,该参数不需要进行设置
XX:SurvivorRatio :Eden 区与 Survivor 区的大小比值,设置为 8,表示 2 个Survivor 区(JVM 堆内存年轻代中默认有 2 个大小相等的 Survivor 区)与 1 个Eden 区的比值为 2:8,即 1 个 Survivor 区占整个年轻代大小的 1/10
XX:+UseSerialGC:设置串行收集器
XX:+UseParallelGC:设置为并行收集器。此配置仅对年轻代有效。即年轻代使用并行收集,而年老代仍使用串行收集
XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集,JDK6.0 开始支持对年老代并行收集
XX:ConcGCThreads:早期 JVM 版本也叫-XX:ParallelCMSThreads,定义并发 CMS过程运行时的线程数。比如 value=4 意味着 CMS 周期的所有阶段都以 4 个线程来执行。尽管更多的线程会加快并发 CMS 过程,但其也会带来额外的同步开销。因此,对于特定的应用程序,应该通过测试来判断增加 CMS 线程数是否真的能够带来性能的提升。如果还标志未设置,JVM 会根据并行收集器中的 -XX:ParallelGCThreads 参数的值来计算出默认的并行 CMS 线程数
XX:ParallelGCThreads:配置并行收集器的线程数,即:同时有多少个线程一起进行垃圾回收,此值建议配置与 CPU 数目相等
XX:OldSize:设置 JVM 启动分配的老年代内存大小,类似于新生代内存的初始大小-XX:NewSize
3.1常见错误说明
java.lang.OutOfMemoryError: Java heap space------JVM Heap(堆)溢出
JVM在启动的时候会自动设置JVM Heap的值,其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)不可超过物理内存。可以利用JVM提供的 -Xmn -Xms -Xmx 等选项来进行设置。Heap的大小是Young Generation和Tenured Generaion之和。在JVM中如果 98%的时间是用于GC,且可用的Heap size不足 2%的时候将抛出此异常信息
解决方法:手动设置 JVM Heap(堆)的大小
java.lang.OutOfMemoryError: PermGen space------PermGen space 溢出PermGen space的全称是Permanent Generation space,是指内存的永久保存区域。为什么会内存溢出,这是由于这块内存主要是被JVM存放Class和Meta信息的,Class在被 Load 的时候被放入PermGen space区域,它和存放Instance的Heap区域不同,sun的GC不会在主程序运行期对PermGen space进行清理。所以,如果你的APP会载入很多CLASS的话,就很可能出现 PermGen space 溢出
解决方法:手动设置 MaxPermSize 大小
java.lang.StackOverflowError------栈溢出JVM依然是采用栈式的虚拟机,这个和C与Pascal都是一样的。函数的调用过程都体现在堆栈和退栈上了。调用构造函数的"层"太多了,以致于把栈区溢出了。通常来讲,一般栈区远远小于堆区的,因为函数调用过程往往不会多于上千层,而即便每个函数调用需要1K 的空间(这个大约相当于在一个 C 函数内声明了 256 个 int 类型的变量),那么栈区也不过是需要 1MB 的空间。通常栈的大小是 1-2MB 的。通常递归也不要递归的层次过多,很容易溢出
解决方法:修改程序
六、Tomcat多实例部署
1.安装 JDK
确保已经安装好 JDK,并配置好环境变量
2.安装Tomcat
这里需要两台虚拟机来完成实验
cd /opt
tar zxvf apache-tomcat-9.0.16.tar.gz
mkdir /usr/local/tomcat
mv apache-tomcat-9.0.16 /usr/local/tomcat/tomcat1
cp -a /usr/local/tomcat/tomcat1 /usr/local/tomcat/tomcat2
3.配置 Tomcat 环境变量
创建环境变量配置文件
vim /etc/profile.d/tomcat.sh
# Tomcat 1
export CATALINA_HOME1=/usr/local/tomcat/tomcat1
export CATALINA_BASE1=/usr/local/tomcat/tomcat1
export TOMCAT_HOME1=/usr/local/tomcat/tomcat1
# Tomcat 2
export CATALINA_HOME2=/usr/local/tomcat/tomcat2
export CATALINA_BASE2=/usr/local/tomcat/tomcat2
export TOMCAT_HOME2=/usr/local/tomcat/tomcat2
使环境变量生效
source /etc/profile.d/tomcat.sh
4.修改 Tomcat 实例配置文件
Tomcat 1 配置文件(默认端口不需修改)
Tomcat 2 配置文件:修改 server.xml 文件中的端口设置
vim /usr/local/tomcat/tomcat2/conf/server.xml
将端口号修改为不同于Tomcat 1的端口
<Server port="8006" shutdown="SHUTDOWN"> <!-- 修改 Server port -->
<!-- 其他配置 -->
</Server>
<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" /> <!-- 修改 HTTP 连接器端口 -->
<Connector port="8010" protocol="AJP/1.3"
redirectPort="8443" /> <!-- 修改 AJP 连接器端口 -->
5.修改启动和关闭脚本
Tomcat 1 启动和关闭脚本
编辑 startup.sh 文件,设置环境变量
vim /usr/local/tomcat/tomcat1/bin/startup.sh
export CATALINA_BASE=$CATALINA_BASE1
export CATALINA_HOME=$CATALINA_HOME1
export TOMCAT_HOME=$TOMCAT_HOME1
编辑 shutdown.sh 文件,设置环境变量
vim /usr/local/tomcat/tomcat1/bin/shutdown.sh
export CATALINA_BASE=$CATALINA_BASE1
export CATALINA_HOME=$CATALINA_HOME1
export TOMCAT_HOME=$TOMCAT_HOME1
Tomcat 2 启动和关闭脚本
编辑 startup.sh 文件,设置环境变量
vim /usr/local/tomcat/tomcat2/bin/startup.sh
export CATALINA_BASE=$CATALINA_BASE2
export CATALINA_HOME=$CATALINA_HOME2
export TOMCAT_HOME=$TOMCAT_HOME2
编辑 shutdown.sh 文件,设置环境变量
vim /usr/local/tomcat/tomcat2/bin/shutdown.sh
export CATALINA_BASE=$CATALINA_BASE2
export CATALINA_HOME=$CATALINA_HOME2
export TOMCAT_HOME=$TOMCAT_HOME2
6.启动Tomcat实例
启动各 Tomcat 实例
/usr/local/tomcat/tomcat1/bin/startup.sh
/usr/local/tomcat/tomcat2/bin/startup.sh
使用 netstat 命令检查端口是否正确
netstat -natp | grep java
浏览器访问测试
http://172.16.58.10:8080
http://172.16.58.10:8081