Tomcat部署及优化

【前置资源】:tomcat前置资源jdk1.8和tomcat9资源-CSDN文库

jvm学习111111111资源-CSDN文库

一、Tomcat概述

Tomcat 是 Java 语言开发的,Tomcat 服务器是一个免费的开放源代码的 Web 应用服务器,是 Apache 软件基金会的 Jakarta 项目中的一个核心项目,由 Apache、Sun 和其他一些公司及个人共同开发而成。


Tomcat 属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试 JSP 程序的首选。一般来说,Tomcat 虽然和 Apache 或者 Nginx 这些 Web 服务器一样,具有处理 HTML 页面的功能,然而由于其处理静态 HTML 的能力远不及 Apache 或者 Nginx,所以 Tomcat 通常是作为一个 Servlet 和 JSP 容器,单独运行在后端。

1.1、tomact端口

tomcat三个端口分别是

  • 8080 web端口
  • 8005 关闭端口
  • 8009 ajp协议端口(默认关闭ajp端口);与其他httpd服务器通信接口,AJP是一种用于将前端(如Apache HTTP服务器)和Tomcat服务器之间连接的二进制协议

在不需要AJP协议的情况下,建议禁用该端口以提高Tomcat服务器的安全性。在server.xml配置文件中注释掉AJP连接器的配置行

AJP协议监听:在Tomcat的默认配置中,8009端口被配置为监听AJP协议。这意味着Tomcat服务器在这个端口上等待来自其他HTTP服务器的AJP请求。

性能优化:AJP协议是一个高效的二进制协议,相比HTTP协议,它可以减少网络传输的数据量,从而提高Web应用程序的响应速度和吞吐量。

安全性:由于AJP协议不是基于文本的,因此它不易于被网络嗅探工具捕获和解析,从而提高了数据传输的安全性。但是Tomcat服务器可能面临来自内部网络的攻击。因此,建议仅在信任的网络环境中使用AJP协议,并通过适当的防火墙规则和安全策略来保护8009端口。

二、Tomcat核心的组件

由一系列的组件构成,其中如下三个是核心:

(1)Web 容器:完成 Web 服务器的功能。

是一个服务器端的软件环境,用于运行Web应用程序,处理HTTP请求和响应。Web容器是Web服务器的一部分,负责管理和执行Web应用程序中的服务器端组件,如Servlet和JSP(JavaServer Pages)

  • 接受,响应请求

  • 展示动态页面

   tomcat web应用服务
   web -->可以通过http(s)来访问的一个页面--->文件
   web容器-->封装了一组文件
   集中化管理-->一组组员的对象
   

(2)Servlet 容器服务器端Java程序):名字为 catalina,用于处理 Servlet 代码。

        定义: Servlet是一种Java编写的服务器端程序,它扩展了服务器的功能,并能够动态生成Web页面。Servlet运行在服务器上,接收来自客户端的请求并产生相应的响应。

 特点:

Servlet是独立于平台的Java类,可以在任何支持Java的服务器上运行。

Servlet通常被用于处理业务逻辑、数据库连接、用户身份验证等服务器端任务。

Servlet生命周期由容器(如Tomcat)管理,包括实例化、初始化、服务请求和销毁等阶段。

使用场景:

处理表单提交、用户登录等Web请求。

与数据库交互,执行业务逻辑。

动态生成HTML内容。


(3)JSP 容器:用于将 JSP 动态网页翻译成 Servlet 代码。

 定义: JSP是一种基于Java的技术,允许在HTML页面中嵌入Java代码。它简化了动态Web页面的创建,使得开发者可以在页面中嵌套Java代码,而无需在Servlet中编写大量的Java代码。

 特点:

JSP页面本质上是包含Java代码的HTML页面,其中的Java代码由特殊的标签(<% %>)包裹。

JSP页面在首次访问时会被容器编译成Servlet,然后由Servlet容器运行。

JSP提供了易于维护和理解的模板化开发方式,允许开发者将Java代码和HTML页面结合起来。

使用场景:

创建动态内容的Web页面。

在HTML页面中嵌套Java代码以执行业务逻辑。

通过使用标签库(Tag Libraries)扩展页面功能。

本质简答的说

简介:

核心组件
web容器:接受、响应请求 ,展示动态页面的,入口和出口
JSP容器:翻译jsp动态网页(java内容)--->servlet代码(因为jsp中java代码无法调用【比如连数据库】,需要翻译为servlet代码)
Serverlet容器:借助于catalina来执行servlet代码(动态任务执行的标准格式)

2.1、运行流程


   
   

2.2、名词解释

a、什么是 JSP?
JSP 全称 Java Server Pages,是一种动态网页开发技术。它使用 JSP 标签在HTML网页中插入 Java 代码。标签通常以 <% 开头,以 %> 结束。
JSP 是一种 Java servlet,主要用于实现 Java web 应用程序的用户界面部分。
JSP 通过网页表单获取用户输入数据、访问数据库及其他数据源,然后动态地创建网页。

b、什么是 servlet?
Servlet 是Java Servlet 的简称,可以理解为是一个服务连接器,是用 Java 编写的服务器端程序,具有独立于平台和协议的特性, 简单的理解:servlet 而实现动态网页的创建。就是一个中间件,包含了接口和方法,将客户端和数据库连接。


  c、动态页面:可以让用户进行交互的一种web的页面
   

  d、后端进行交互  怎么打开交互页面展示
   index.jsp---> tomcat用的   java 环境 -----和数据交互 

因此 Tomcat 是 Web 应用服务器,也是一个 Servlet/JSP 容器。Tomcat 作为 Servlet 容器,负责处理客户请求,把请求传送给 Servlet,并将 Servlet 的响应传送回给客户。

三、Tomcat 功能组件结构

Tomcat 的核心功能有两个,分别是负责接收和反馈外部请求的连接器 Connector,和负责处理请求的容器 Container。 其中连接器和容器相辅相成,一起构成了基本的 web 服务 Service。每个 Tomcat 服务器可以管理多个 Service。

●Connector:负责对外接收和响应请求。它是Tomcat与外界的交通枢纽,监听端口接收外界请求,并将请求处理后传递给容器做业务处理,最后将容器处理后的结果响应给外界。
●Container:负责对内处理业务逻辑。其内部由 Engine、Host、Context和Wrapper 四个容器组成,用于管理和调用 Servlet 相关逻辑。
●Service:对外提供的 Web 服务。主要包含 Connector 和 Container 两个核心组件,以及其他功能组件。Tomcat 可以管理多个 Service,且各 Service 之间相互独立。
 

3.1、Container 结构分析

容器 有一个引擎可以管理多个虚拟主机。每个虚拟主机可以管理多个 Web 应用。每个 Web 应用会有多个 Servlet 封装器。

每个 Service 会包含一个 Container 容器。在 Container 内部包含了 4 个子容器:
4个子容器的作用分别是:
(1)Engine:引擎,用来管理多个虚拟主机,一个 Service 最多只能有一个 Engine;
(2)Host:代表一个虚拟主机,也可以叫站点,通过配置 Host 就可以添加站点;
(3)Context:代表一个 Web 应用,包含多个 Servlet 封装器;
(4)Wrapper:封装器,容器的最底层。每一 Wrapper 封装着一个 Servlet,负责对象实例的创建、执行和销毁功能。

Engine、Host、Context 和 Wrapper,这四个容器之间属于父子关系。

3.2、Tomcat 请求过程:

1、用户在浏览器中输入网址,请求被发送到本机端口 8080,被在那里监听的 Connector 获得;
2、Connector 把该请求交给它所在的 Service 的 Engine(Container)来处理,并等待 Engine 的回应;
3、请求在 Engine、Host、Context 和 Wrapper 这四个容器之间层层调用,最后在 Servlet 中执行对应的业务逻辑、数据存储等。
4、执行完之后的请求响应在 Context、Host、Engine 容器之间层层返回,最后返回给 Connector,并通过 Connector 返回给客户端。

扩展 详细请求过程
假设来自客户的请求为: http://localhost:8080/hhh/hhh_index.jsp 
1) 请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得 
2) Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应 
3) Engine获得请求localhost/hhh/hhh_index.jsp,匹配它所拥有的所有虚拟主机Host 
4) Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机) 
5) localhost Host获得请求/hhh/hhh_index.jsp,匹配它所拥有的所有Context 
6) Host匹配到路径为/hhh的Context(如果匹配不到就把该请求交给路径名为""的Context去处理) 
7) path="/hhh"的Context获得请求/hhh_index.jsp,在它的mapping table中寻找对应的servlet 
8) Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类 
9) 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法 
10)Context把执行完了之后的HttpServletResponse对象返回给Host 
11)Host把HttpServletResponse对象返回给Engine 
12)Engine把HttpServletResponse对象返回给Connector 
13)Connector把HttpServletResponse对象返回给客户browser

四、Tomcat 服务部署

tomcat官网网站下载:https://tomcat.apache.org/download-90.cgi
JDK官方下载:https://www.oracle.com/java/technologies/downloads/#java22

或者【前置资源】

在部署 Tomcat 之前必须安装好 jdk,因为 jdk 是 Tomcat 运行的必要环境。

1.关闭防火墙,将安装 Tomcat 所需软件包传到/opt目录下
jdk-8u201-linux-x64.rpm
apache-tomcat-9.0.16.tar.gz

systemctl stop firewalld
systemctl disable firewalld
setenforce 0

2.安装JDK

rpm -ivh jdk-8u201-linux-x64.rpm

3.设置JDK环境变量 

vim /etc/profile.d/java.sh

export JAVA_HOST=/usr/java/jdk1.8.0_201-amd64
export CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar
export PATH=$JAVA_HOST/bin:$PATH

刷新

source /etc/profile.d/java.sh

查看版本

java -version  发现改变为企业版本

补充

---------------------------------------------------------小知识-----------------------------------------------------------
CLASSPATH:编译、运行Java程序时,JRE会去该变量指定的路径中搜索所需的类(.class)文件。
dt.jar:是关于运行环境的类库,主要是可视化的 swing 的包。
tools.jar:主要是一些jdk工具的类库,包括javac、java、javap(jdk自带的一个反编译工具)、javadoc等。
JDK :java development kit (java开发工具)
JRE :java runtime environment (java运行时环境)
JVM :java virtuak machine (java虚拟机),使java程序可以在多种平台上运行class文件。
--------------------------------------------------------------------------------------------------------------------------------

4、安装启动Tomcat

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 start
    
#前台启动
/usr/local/tomcat/bin/catalina.sh run

这个只是暂时的启动,关闭会停止

netstat -natp | grep 8080

浏览器访问Tomcat的默认主页 http://192.168.80.100:8080

5、添加到系统服务来启动

新建tomcat系统用户
useradd -s /sbin/nologin tomcat
修改属主和属组
chown tomcat:tomcat  /usr/local/tomcat/  -R

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


systemctl daemon-reload
systemctl start tomcat
ss -ntap |grep 8080

五、优化tomcat启动速度

第一次启动tomcat可能会发现 Tomcat 启动很慢,默认情况下可能会需要几十秒,可以修改jdk参数进行改。

vim /usr/java/jdk1.8.0_201-amd64/jre/lib/security/java.security

--117行--修改
securerandom.source=file:/dev/urandom

/dev/urandom是/dev/random的非阻塞版本,/dev/random的 random pool 依赖于系统中断,因此在系统的中断数不足时,/dev/random 设备会一直封锁,尝试读取的进程就会进入等待状态,直到系统的中断数充分够用,/dev/random设备可以保证数据的随机性。 /dev/urandom不依赖系统的中断,也就不会造成进程忙等待,但是数据的随机性也不高,所以该随机数的安全性理论上不高。如果应用对安全性要求很高,那么应该使用/dev/random
 

/usr/local/tomcat/bin/shutdown.sh 
/usr/local/tomcat/bin/startup.sh 

5.1、主要目录说明

ll /usr/local/tomcat/
------主要目录说明------------------------------------------------------------------------------------------------------
●bin:存放启动和关闭Tomcat的脚本文件,比较常用的是 catalina.sh、startup.sh、shutdown.sh三个文件
●conf:存放Tomcat 服务器的各种配置文件,比较常用的是 server.xml、context.xml、tomcat-users.xml、web.xml 四个文件。
① server.xml: Tomcat的主配置文件,包含Service,Connector,Engine,Realm,Valve,Hosts主组件的相关配置信息;
② context.xml:所有host的默认配置信息;
③ tomcat-user.xml:Realm认证时用到的相关角色、用户和密码等信息,Tomcat自带的manager默认情况下会用到此文件,在Tomcat中添加/删除用户,为用户指|定角色等将通过编辑此文件实现;
④ web.xml:遵循Servlet规范标准的配置文件,用于配置servlet,并为所有的web应用程序提供包括MIME映射等默认配置信息;
●lib:存放Tomcat运行需要的库文件的jar 包,一般不作任何改动,除非连接第三方服务,比如 redis,那就需要添加相对应的jar 包
●logs:存放 Tomcat 执行时的日志
●temp:存放 Tomcat 运行时产生的文件
●webapps:存放 Tomcat 默认的 Web 应用部署目录
●work:Tomcat工作日录,存放jsp编译后产生的class文件,一般清除Tomcat缓存的时候会使用到
●src:存放Tomcat 的源代码
●doc:存放Tomcat文档
---------------------------------------------------------------------------------------------------------------------------------

5.2、Tomcat 虚拟主机配置

很多时候公司会有多个项目需要运行,一般不会是在一台服务器上运行多个 Tomcat 服务,这样会消耗太多的系统资源。此时, 就需要使用到 Tomcat 虚拟主机。


例如现在新增两个域名过这两个域名访问到不同的项目内容。
 www.kgc.com 和 www.benet.com, 希望通
1.创建 yc 和 hhh 项目目录和文件
mkdir /usr/local/tomcat/webapps/yc
mkdir /usr/local/tomcat/webapps/hhh
echo "This is kgc page\!" > /usr/local/tomcat/webapps/yc/index.jsp
echo "This is benet page\!" > /usr/local/tomcat/webapps/hhh/index.jsp

2.修改 Tomcat 主配置文件 server.xml
vim /usr/local/tomcat/conf/server.xml
--165行前--插入

      <Host name="www.yc.com" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
        <Context docBase="/usr/local/tomcat/webapps/yc" path="" reloadable="true" />
        </Host>

        <Host name="www.hhh.com" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
        <Context docBase="/usr/local/tomcat/webapps/hhh" path="" reloadable="true" />
        </Host>

内容解释

appBase:Tomcat程序工作目录,即存放web应用程序的目录;相对路径为webapps,绝对路径为 /usr/local/tomcat/webapps
unpackWARs:在启用此webapps时是否对WAR格式的归档文件先进行展开;默认为true
autoDeploy:在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy;默认为true
xmlValidation:是否验证xml文件执行有效性检验的标志
xmlNamespaceAware:是否启用xml命名空间,设置该值与xmlValidation为true,表示对web.xml文件执行有效性检验

docBase:相应的Web应用程序的存放位置;也可以使用相对路径,起始路径为此Context所属Host中appBase定义的路径;
path:相对于Web服务器根路径而言的URI;如果为空“”,则表示为此webapp的根路径 / ;
reloadable:是否允许重新加载此context相关的Web应用程序的类;默认为false

/usr/local/tomcat/bin/shutdown.sh     关闭 
/usr/local/tomcat/bin/startup.sh      启动

3.客户端浏览器访问验证

echo "你的主机地址  www.yc.com www.hhh.com" >> /etc/hosts

浏览器访问 http://www.yc.com:8080/   页面显示This is kgc page\! 
浏览器访问 http://www.hhh.com:8080/   页面显示This is benet page\!

HTTP 请求过程:
(1)Connector 连接器监听的端口是 8080。由于请求的端口和监听的端口一致,连接器接受了该请求。
(2)因为引擎的默认虚拟主机是 www.yc.com,并且虚拟主机的目录是webapps。所以请求找到了 tomcat/webapps 目录。
(3)访问的路径为根路径,URI 为空,即空是 Web 程序的应用名,也就是 context。此时请求找到 /usr/local/tomcat/webapps/yc目录,解析 index.jsp 并返回。

六、Tomcat 优化

Tomcat默认安装下的缺省配置并不适合生产环境,它可能会频繁出现假死现象需要重启,只有通过不断压测优化才能让它最高效率稳定的运行。

不要立马调优需要不断测试

优化主要包括三方面,分别为

  • 操作系统优化(内核参数优化)
  • Tomcat配置文件参数优化
  • Java虚拟机(JVM)调优

6.2、Tomcat 配置文件参数优化

官方:链接地址 Apache Tomcat 9 Configuration Reference (9.0.93) - The HTTP Connector

常用的优化相关参数如下:

参数名称描述默认值
redirectPort当HTTP连接器接收到HTTPS请求时,转发到的端口未设置
maxThreadsTomcat可创建的最大线程数(即最大并发连接数)200
minSpareThreads最小空闲线程数(Tomcat启动时初始化的线程数)10
maxSpareThreads最大备用线程数(超过此值则关闭不再需要的线程)-1(无限制)
URIEncodingTomcat容器的URL编码格式ISO-8859-1(依赖于服务器版本和配置)
connectionTimeout网络连接超时时间(毫秒)20000(20秒)
enableLookups是否反查域名以返回远程主机的主机名true
disableUploadTimeout上传时是否禁用超时机制false(但通常建议设置为true)
connectionUploadTimeout上传超时时间(毫秒)未设置(需与disableUploadTimeout配合使用)
acceptCount当所有处理请求的线程都被使用时,可传入连接请求的最大队列长度100
compression是否对响应数据进行GZIP压缩off
compressionMinSize压缩响应的最小值(字节)2048
compressableMimeType指定对哪些类型的文件进行数据压缩未设置(需要具体指定MIME类型)
noCompressionUserAgents对于哪些用户代理不启用压缩未设置

以上是一些常用的配置参数,还有好多其它的参数设置,还可以继续深入的优化,HTTP Connector 与 AJP Connector 的参数属性值,可以参考官方文档的详细说明进行学习。

vim /usr/local/tomcat/conf/server.xml

<Connector port="8080" protocol="HTTP/11.1" 
connectionTimeout="20000" 
redirectPort="8443" 
---------------------------71行下--插入:注意在<>内-------------------------------------
minSpareThreads="50" 
enableLookups="false" 
disableUploadTimeout="true" 
acceptCount="300" 
maxThreads="500" 
processorCache="500"
URIEncoding="UTF-8" 
compression="on" 
compressionMinSize="2048" 
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,image/gif,image /jpg,image/png"/>

6.3、JVM调优

6.3.1、JVM是什么?

JVM是Java Virtual Machine的简称,它是一个虚拟的计算机,专门为执行Java程序而设计。

你可以想象它是一个能够运行Java字节码的平台,无论你的程序在Windows、Mac还是Linux上,它们都能通过JVM在这些系统中平稳运行。

JVM让Java程序摆脱了具体硬件和操作系统的限制。这就是为什么你可以在任何安装了JVM的设备上运行同一个Java程序。

JVM将内存划分为:

1.New(年轻代)年轻代用来存放JVM刚分配的Java对象
2.Tenured(年老代)轻代中经过垃圾回收没有回收掉的对象将被Copy到年老代
3.永久代(Perm)(备注:jdk1.8之后 改为元本地元空间)  永久代存放Class、Method元信息,其大小跟项目的规模、类、方法的量有关,一般设置为128M就足够,设置原则是预留30%的空间。

 其中,New和Tenured属于堆内存。-xmx:指定jvm堆内存最大值,-xms:jvm堆初始化值。

   永久代,Perm(非堆)不属于堆内存,由虚拟机直接分配,但可以通过

   -XX:PermSize -XX:MaxPermSize等参数调整其大小。

其他详细内容【前置】

6.3.2、Tomcat中调jvm(包括一些参数)

Tomcat 启动命令行中的优化参数,就是 JVM 的优化 。

Tomcat 是 Java 程序,运行在 JVM 之上,因为它的启动其实也只是一个 Java 命令行,我们需要对这个 Java 的启动命令行进行调优。

程序在上线前的测试或运行中有时会出现一些大大小小的JVM问题,比如cpu load过高、请求延迟、tps降低等,甚至出现内存泄漏(每次垃圾收集使用的时间越来越长,垃圾收集频率越来越高,每次垃圾收集清理掉的垃圾数据越来越少)、内存溢出导致系统崩溃,因此需要对JVM进行调优,使得程序在正常运行的前提下,获得更高的用户体验和运行效率。

不管是YGC(Young Generation Collection,年轻代垃圾收集)还是Full GC(Full Garbage Collection,全堆垃圾收集),GC(Garbage Collection,垃圾收集)确实都会导致程序运行的中断(这主要是由于GC过程的性质决定的)

正确的选择不同的 GC 策略,调整 JVM、GC 的参数,可以极大的减少由于 GC 工作而导致的程序运行中断方面的问题,进而适当的提高 Java 程序的工作效率。但是调整 GC 是一个极为复杂的过程,由于各个程序具备不同的特点,如 Web 和 GUI 程序就有很大区别(Web 可以适当的停顿,但 GUI 停顿是客户无法接受的),而且由于运行在各个机器上的配置不同(主要 CPU个数,内存不同),所以使用的 GC 种类也会不同。

Tomcat 的启动参数位于安装目录 ${JAVA_HOME}/bin 目录下,Linux 操作系统就是catalina.sh 文件。Java_OPTS 就是用来设置 JVM 相关运行参数的变量,下面具体看 JVM常用参数详解。

/bin/catalina.sh


-server:jvm的server工作模式(长途),对应的有client工作模式(小轿车)。

使用“java -version”可以查看当前工作模式

在vim  /usr/local/tomcat/bin/catalina.sh找到JAVA_OPTS修改

或者

如果不存在,Tomcat的安装目录下的bin文件夹创建,一个新文件并命名为setenv.sh,

通常推荐在setenv.sh中设置(以避免直接修改Tomcat的默认脚本),设置CATALINA_OPTSJAVA_OPTS环境变量来指定JVM的内存参数。例如:

export CATALINA_OPTS="-Xms512m -Xmx1024m"

这里-Xms指定了JVM的初始堆内存大小,-Xmx指定了JVM的最大堆内存大小。

参数描述
-server强制JVM以服务器模式运行,适用于生产环境。
-Xms设置Java的初始大小。建议与-Xmx设置相同值以避免JVM频繁调整堆大小。
-Xmx设置Java堆的最大大小。建议设置为物理内存的50%以避免内存溢出。
-XX:NewSize设置新生代的初始内存大小。应该小于 -Xms的值
-XX:MaxNewSize表示新生代可被分配的内存的最大上限,应该小于 -Xmx的值
-XX:PermSize(已废弃,Java 8+使用元空间)元空间(Metaspace)代替)设置永久代的初始大小。在Java 8及更高版本中由元空间代替。
-XX:MaxPermSize(已废弃,Java 8+使用元空间)设置永久代的最大大小。在Java 8及更高版本中由元空间代替。
-XX:+AggressiveOpts启用JVM的优化选项,随着JDK版本升级自动使用新的优化技术。
-XX:+UseBiasedLocking启用偏向锁,优化线程锁的性能。
-XX:+DisableExplicitGC禁用System.gc()调用,防止程序员在代码中手动触发GC。自动将System.gc() 调用转换成一个空操作,即应用中调用System.gc()
会变成一个空操作,避免程序员在代码里进行System.gc()这种危险操作。System.gc()
除非是到了万不得也的情况下使用,都应该交给 JVM。
-XX:+UseParNewGC对新生代使用并行垃圾收集器。
-XX:MaxTenuringThreshold设置对象在新生代中存活的最大年龄,达到后晋升到老年代。
-XX:+CMSParallelRemarkEnabled在使用CMS收集器时,优化mark过程,减少时间消耗。
-XX:+UseCMSCompactAtFullCollection在CMS垃圾收集后,对内存进行压缩,减少碎片。
-XX:LargePageSizeInBytes设置Java堆的分页页面大小,注意与Perm大小的关系。
-XX:+UseFastAccessorMethods使用本地代码优化get和set方法的性能。
-XX:+UseCMSInitiatingOccupancyOnly仅当老年代占用率达到指定比例时,CMS收集器才启动。
-Duser.timezone=Asia/Shanghai设置用户时区。
-Djava.awt.headless=true在无头模式下运行,适用于服务器环境,避免图形界面相关问题。
-Xmn设置新生代的内存大小,包括Eden和两个Survivor区。
-XX:CMSInitiatingOccupancyFraction设置CMS收集器在老年代占用率达到此比例时启动。
-XX:+CMSIncrementalMode启用CMS收集器的增量模式,适用于CPU资源受限的环境。
-XX:NewRatio设置年轻代与年老代的比值(不包括永久代)。
-XX:SurvivorRatio设置Eden区与Survivor区的比例。
-XX:+UseSerialGC使用串行垃圾收集器。(1)
-XX:+UseParallelGC对年轻代使用并行垃圾收集器,年老代仍使用串行收集器(除非配合-XX:+UseParallelOldGC)。(2)
-XX:+UseParallelOldGC对年老代也使用并行垃圾收集器。
-XX:ConcGCThreads设置并发CMS收集器的线程数。
-XX:ParallelGCThreads设置并行垃圾收集器的线程数,建议与CPU核心数相同。
-XX:OldSize设置JVM启动时分配给老年代的内存大小(不常用,通常与-Xms-Xmx一起调整)。

配置思路需要考虑的是Java 提供的垃圾回收机制。虚拟机的堆大小决定了虚拟机花费在收集垃圾上的时间和频度。收集垃圾能够接受的速度和应用有关,应该通过分析实际的垃圾收集的时间和频率来调整。假如堆的大小很大,那么完全垃圾收集就会很慢,但是频度会降低。假如您把堆的大小和内存的需要一致,完全收集就很快,但是会更加频繁。调整堆大小的目的是最小化垃圾收集的时间,以在特定的时间内最大化处理客户的请求。在基准测试的时候,为确保最好的性能,要把堆的大小设大,确保垃圾收集不在整个基准测试的过程中出现。

6.3.3、常见错误

 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 的。通常递归也不要递归的层次过多,很容易溢出。

解决方法:修改程序。

6.3.4、一些工具

jps:用来显示本地的java进程,以及进程号,进程启动的路径等。

其中 Bootstrap进程就是我们启动了的 Tomcat,其进程号为49058

jmap:观察运行中的JVM 物理内存的占用情况,包括Heap size , Perm size

利用 jmap工具查看其内存相关配置:

若内存不足,显示500错误,一般调整Xms和Xmx,可以将Xms和Xmx设置成一样

使用:set JAVA_OPTS=-Xms512m-Xmx512m

6.3.5、一些补充

1、内存溢出:OOM(out of memory)

当应用程序所需的最大内存超过了系统为其分配的内存时,就会发生内存溢出。

比如:运行一个应用程序需要4g内存,项目只支持3g内存 溢出

解决:

增加内存限制、

  • 可以通过调整Tomcat的启动参数来增加最大堆内存。使用-Xmx参数来设置JVM能够使用的最大内存量。例如,设置-Xmx4g以允许Tomcat使用最多4GB的内存。
  • -Xms用于设置JVM启动时的初始堆内存大小,这也有助于避免内存使用过程中的频繁GC(垃圾回收)。
  • -Xmn用于设置年轻代(Young Generation)的大小,但这个参数不常用,且需谨慎设置,因为它会影响到垃圾回收的效率。

优化代码、

  • 检查代码中是否有不必要的大对象创建,或者在循环中错误地创建对象而未及时释放。
  • 使用合理的数据结构来减少内存占用,比如使用StringBuilder而非String进行大量字符串拼接。
  • 检查是否有数据被长时间缓存在内存中而未被使用,例如使用缓存时应设置合理的过期时间。

配置垃圾回收器

  • 根据应用特点选择合适的垃圾回收器。JVM提供了多种垃圾回收器,如Parallel GC、CMS、G1等,每种都有各自的适用场景。
  • 可以通过-XX:+UseG1GC等参数来启用G1垃圾回收器,它更适合大内存和多核CPU的环境。

Tomcat垃圾回收机制:垃圾回收机制会不定时的向堆内存中清理不可达(没有被程序引用)的对象。 

2、内存泄露:

内存泄露指的是应用中的对象由于某种原因(如长时间保持引用)而无法被垃圾回收器回收,从而导致内存不断减少,最终可能导致OOM。

比如:程序中定义很多静态变量,但是垃圾回收机制不会进行回收,这个对象没有被引用,再次申请内存,会报错泄露。

解决:

分析内存使用情况

避免静态字段引用大量数据

使用finalize方法需谨慎

避免不必要的对象引用

finalize方法:java虚拟机在垃圾回收之前会先调用垃圾对象的finalize方法。(因为垃圾回收机制只负责回收内存,并不负责资源的回收,资源回收要由程序员完成)。

final方法:用于修饰类、成员变量和成员方法。final修饰的类不能被继承,其中所有的方法都不能被重写所以不能同时使用abstract(抽象类是用于被子类继承的和final起相反的作用)和final修饰类。

6.4、Tomcat多实例部署

1.安装好 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/tomcat23.配置 tomcat 环境变量


vim /etc/profile.d/tomcat.sh

#tomcat1
export CATALINA_HOME1=/usr/local/tomcat/tomcat1
export CATALINA_BASE1=/usr/local/tomcat/tomcat1
export TOMCAT_HOME1=/usr/local/tomcat/tomcat1

#tomcat2
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.修改 tomcat2 中的 server.xml 文件,要求各 tomcat 实例配置不能有重复的端口号

vim /usr/local/tomcat/tomcat2/conf/server.xml

#22行,修改Server prot,默认为8005 -> 修改为8006
<Server port="8006" shutdown="SHUTDOWN">        
#69行,修改Connector port,HTTP/1.1  默认为8080 -> 修改为8081
<Connector port="8081" protocol="HTTP/1.1"        
#116行,修改Connector port AJP/1.3,默认为8009 -> 修改为8010
<Connector port="8010" protocol="AJP/1.3" redirectPort="8443" />    

----------------------------------------------------------------------------------------------------------
第一个连接器默认监听8080端口,负责建立HTTP连接。在通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个连接器。
第二个连接器默认监听8009端口,负责和其他的HTTP服务器建立连接。在把Tomcat与其他HTTP服务器集成时,就需要用到这个连接器。
----------------------------------------------------------------------------------------------------------

5.修改各 tomcat 实例中的 startup.sh 和 shutdown.sh 文件,添加 tomcat 环境变量

vim /usr/local/tomcat/tomcat1/bin/startup.sh

# -----------------------------------------------------------------------------
# Start Script for the CATALINA Server
# -----------------------------------------------------------------------------
# 添加以下内容
export CATALINA_BASE=$CATALINA_BASE1
export CATALINA_HOME=$CATALINA_HOME1
export TOMCAT_HOME=$TOMCAT_HOME1


vim /usr/local/tomcat/tomcat1/bin/shutdown.sh

# -----------------------------------------------------------------------------
# Stop script for the CATALINA Server
# -----------------------------------------------------------------------------
export CATALINA_BASE=$CATALINA_BASE1
export CATALINA_HOME=$CATALINA_HOME1
export TOMCAT_HOME=$TOMCAT_HOME1

-------------------------------------------------------------------------------------------------------------------------------


vim /usr/local/tomcat/tomcat2/bin/startup.sh

# -----------------------------------------------------------------------------
# Start Script for the CATALINA Server
# -----------------------------------------------------------------------------
export CATALINA_BASE=$CATALINA_BASE2
export CATALINA_HOME=$CATALINA_HOME2
export TOMCAT_HOME=$TOMCAT_HOME2


vim /usr/local/tomcat/tomcat2/bin/shutdown.sh

# -----------------------------------------------------------------------------
# Stop script for the CATALINA Server
# -----------------------------------------------------------------------------
export CATALINA_BASE=$CATALINA_BASE2
export CATALINA_HOME=$CATALINA_HOME2
export TOMCAT_HOME=$TOMCAT_HOME2

6.启动各 tomcat 中的 /bin/startup.sh 
/usr/local/tomcat/tomcat1/bin/startup.sh 
/usr/local/tomcat/tomcat2/bin/startup.sh 

netstat -natp | grep java

7.浏览器访问测试
http://192.168.88.79:8080
http://192.168.88.79:8081

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值