当前位置: 首页 > news >正文

Tomcat的部署及调优,jvm调优

一,tomcat相关知识

1.1,tomcat介绍

tomcat是一个开源的Web应用服务器,属于轻量级应用服务器,由Apache软件基金会维护,是Jakarta项目中的一个核心项目。它由Apache、Sun和其他一些公司及个人共同开发,由于Sun的支持,Tomcat能够体现最新的Servlet和JSP规范。Tomcat因其技术先进、性能稳定且免费,受到Java爱好者的喜爱,并被部分软件开发商认可,成为流行的Web应用服务器。

Tomcat服务器支持Servlet和JSP规范,允许用户运行Java Web应用程序。它能够接收和解析来自客户端的请求,并将这些请求转发给相应的Servlet或JSP文件,处理客户端的响应。Tomcat作为一个Servlet容器,负责创建ServletRequest和ServletResponse对象,并调用请求的Servlet或JSP文件的服务方法,将请求参数传递给这些方法。

Tomcat可以独立运行,不依赖于Apache服务器,但通常与Apache结合使用。Apache服务器负责响应HTML页面请求,而Tomcat则处理JSP页面和Servlet,提供动态内容。Tomcat还支持静态HTML内容,尽管它在处理静态HTML方面不如Apache服务器。

Tomcat是完全用Java编写的,可以在多种操作系统上运行,包括Windows、Linux和macOS。它的官方网站提供了下载和文档,用户可以根据需要选择合适的版本进行安装和使用。目前,Tomcat的最新版本是8.0。

1.2,tomcat的组件构成

web容器:完成web服务器的功能。

servlet容器:名字为catalina,用于处理servlet代码。

jsp容器:用于将jsp动态网页翻译成servlet代码

1.3,tomcat的功能组件结构

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

Connector:负责对外接收和响应请求。它是Tomcat与外界的交通枢纽,监听端口接收外界请求,并将请求处理后传递给容器做业务处理,最后将容器处理后的结果响应给外界。

Container:负责对内处理业务逻辑。其内部由 Engine、Host、Context和Wrapper 四个容器组成,用于管理和调用 Servlet 相关逻辑。

Service:对外提供的 Web 服务。主要包含 Connector 和 Container 两个核心组件,以及其他功能组件。Tomcat 可以管理多个 Service,且各 Service 之间相互独立。

1.4,tomcat的请求过程

1,连接器(connector)接受请求:负责接收输入的tcp连接请求,并创建一个request和response对象用于交互。

2,容器(container)处理请求:tomcat中的容器由Engine、Host、Context和Wrapper组成,用于处理请求并返回响应。

3,容器处理如何请求:

  • 请求首先发送到Engine级别,进行交叉匹配。

  • 如果没有匹配,请求将 bubble(冒泡)到上一级 Host,再次进行匹配。

  • 如果仍然没有匹配,请求继续在 Context 级别进行匹配,这里通常对应具体的应用。

  • 最后,如果仍然没有匹配的Wrapper,Tomcat将返回404错误。

4,响应:一旦容器确定了处理这个请求的Wrapper,请求就会被传递给对应的Servlet来处理。Servlet处理完请求后,将响应返回给容器。

5,响应返回给连接器:最后容器将Servlet处理的响应返回给Connector,并通过Socket发送回客户端。

以下是一个简化的Tomcat请求处理过程的伪代码示例:

// 1. 连接器接收请求
Socket socket = acceptConnection(); // 接收TCP连接
Request request = parseRequest(socket); // 解析请求
Response response = new Response(); // 创建响应对象// 2. 容器处理请求
Engine engine = getEngine();
engine.process(request, response);// 代码函数process的一个简化版本
void Engine::process(Request request, Response response) {// 匹配请求到适当的HostHost host = this.findHost(request);host.process(request, response);// ... 其他容器处理逻辑
}// Servlet处理请求
if (servletFound) {servlet.service(request, response);
} else {response.sendError(404); // 发送404错误
}// 3. 响应返回给连接器
sendResponse(socket, response); // 将响应发送回客户端

二,tomcat服务部署

参考博客:csdn:xiaoyaoxiangnila    第七点 jdk及tomcat的安装

三,tomcat的优化

1、增加 Tomcat 的内存分配:可以通过调整 Tomcat 的启动脚本来增加其分配的内存,比如在 catalina.sh 或 catalina.bat 中设置环境变量 CATALINA_OPTS 为 -Xms512m -Xmx1024m,其中 -Xms 表示 Tomcat 启动时分配的最小内存, -Xmx 表示 Tomcat 允许使用的最大内存。

2、调整 Tomcat 的线程池设置:Tomcat 默认使用的线程池是 org.apache.tomcat.util.threads.ThreadPoolExecutor,可以通过修改 server.xml 中的 Connector 节点下的 maxThreads、minSpareThreads 和 acceptCount 参数来调整线程池的大小和性能。

3、优化 Tomcat 的缓存设置:可以通过调整 server.xml 中的 Connector 节点下的 enableLookups、maxKeepAliveRequests 和 keepAliveTimeout 等参数来优化 Tomcat 的缓存设置,减少网络连接的开销。

4、启用压缩:可以在 server.xml 中的 Connector 节点下启用压缩来减少网络传输的数据量,提高网站的响应速度,比如设置 compression 参数为 on、compressionMinSize 参数为 2048 等。

5、启用静态资源缓存:可以通过在 web.xml 中配置 filter,启用静态资源缓存,减少服务器的负载,提高访问速度。

6、使用 CDN 加速静态资源:可以使用 CDN(内容分发网络)来加速静态资源的传输,减少服务器的负载,提高网站的访问速度。

7、避免使用过多的 Session:可以在编写 Web 应用程序时避免过多地使用 Session,因为 Session 会占用服务器的内存资源,从而影响 Tomcat 的性能。

8、避免过多的 JDBC 操作:可以在编写 Web JDBC 操作数据库,因为数据库的访问是非常耗时的,从而影响 Tomcat 的性能。

 

优化这一部分仅供参考。

四,Tomcat性能调优

找到Tomcat根目录下的conf目录,修改server.xml文件的内容。对于这部分的调优,我所了解到的就是无非设置一下Tomcat服务器的最大并发数和Tomcat初始化时创建的线程数的设置,当然还有其他一些性能调优的设置,下图是我根据我机子的性能设置的一些参数值,给各位详细解释一下吧:

1、URIEncoding=“UTF-8”:设置Tomcat的字符集。这种配置我们一般是不会设置的,因为关于乱码的转换我们会在具体项目中具体处理,直接修改Tomcat的字符集未免过于太死板。

2、maxThreads=“300”:设置当前Tomcat的最大并发数。Tomcat默认配置的最大请求数是150个,即同时能支持150个并发。但是在实际运用中,最大并发数与硬件性能和CPU数量都有很大关系的,更好的硬件、更高的处理器都会使Tomcat支持更多的并发数。如果一般在实际开发中,当某个应用拥有 250 个以上并发的时候,都会考虑到应用服务器的集群。

3、minSpareThreads=“50”:设置当前Tomcat初始化时创建的线程数,默认值为25。

4、acceptCount=“250”:当同时连接的人数达到maxThreads参数设置的值时,还可以接收排队的连接数量,超过这个连接的则直接返回拒绝连接。指定当任何能够使用的处理请求的线程数都被使用时,能够放到处理队列中的请求数,超过这个数的请求将不予处理。默认值为100。在实际应用中,如果想加大Tomcat的并发数 ,应该同时加大acceptCount和maxThreads的值。整编:微信公众号,搜云库技术团队,ID:souyunku

5、enableLookups=“false”:是否开启域名反查,一般设置为false来提高处理能力,它的取值还有true,一般很少使用。

6、maxKeepAliveRequests=“1”:nginx动态的转给tomcat,nginx是不能keepalive的,而tomcat端默认开启了keepalive,会等待keepalive的timeout,默认不设置就是使用connectionTimeout。所以必须设置tomcat的超时时间,并关闭tomcat的keepalive。否则会产生大量tomcat的socket timewait。maxKeepAliveRequests=”1”就可以避免tomcat产生大量的TIME_WAIT连接,从而从一定程度上避免tomcat假死。

1,调整tomcat线程池

2,调整tomcat的连接器

调整tomcat/conf/server.xml 中关于链接器的配置可以提升应用服务器的性能。

参数及其说明:

maxconnetions:最大连接数,当到达该值后,服务器接收但不会处理更多的请求,额外的请求将会阻塞直到连接数低于maxconnections。可以通过ulimit - a查看服务器限制,对于cpu要求更高时,建议不用配置过大,对于cpu要求时,建议配置在2000左右,当然这个需要服务器硬件的支持。

maxthreads:最大线程数,需要更具服务器的硬件情况进行配置。

acceptcount:最大排队等待数,当服务器接收的请求到达maxconnections,此时tomcat会将后面的请求存放在任务队列中进行排序,acceptcount指的是任务队列中排队等待的请求数,一台tomcat的最大请求请求处理数量,是maxconnetions+acceptcount

3,禁用AJP连接器

4,调整io模式

Tomcat8之前的版本默认使用BIO(阻塞式IO),对于每一个请求都要创建一个线程来处理,不适
合高并发;Tomcat8以后的版本默认使用NIO模式(非阻塞式IO)。

当Tomcat并发性能有较高要求或者出现瓶颈时,我们可以尝试使用APR模式,APR(Apache Portable Runtime)是从操作系统级别解决异步IO问题,使用时需要在操作系统上安装APR和Native(因为APR 原理是使用使用JNI技术调用操作系统底层的IO接口)

5,动态分离

可以使用Nginx+Tomcat相结合的部署方案,Nginx负责静态资源访问,Tomcat负责Jsp等动态资源访问处理(因为Tomcat不擅⻓处理静态资源)。

五、jvm优化(参数调整)

Java 虚拟机的运行优化主要是内存分配和垃圾回收策略的优化:

  • 内存直接影响服务的运行效率和吞吐量
  • 垃圾回收机制会不同程度地导致程序运行中断(垃圾回收策略不同,垃圾回收次数和回收效率都是 不同的)
  • Tomcat本身还是运行在JVM上的,通过对JVM参数的调整我们可以使Tomcat拥有更好的性能。目前针对JVM的调优主要有两个方面:内存调优和垃圾回收策略调优。

 Java 虚拟机内存相关参数

参数参数作用优化建议
-server启动server,以服务端模式运行服务器模式建议开启
-xms最小堆内存建议与-xmx设置相同
-xmx最大堆内存建议设置为可用内存的80%
-xx:metaspacesize元空间初始值
-xx:maxmetaspacesize元空间最大内存默认无限
-xx:newratio取整数,默认为2不需要修改
-xx:survivoratio取整数,默认值为8

不需要修改

参数调整:

JAVA_OPTS="-server -Xms2048m -Xmx2048m -XX:MetaspaceSize=256m - XX:MaxMetaspaceSize=512m"

 4、调整后查看可使用JDK提供的内存映射工具

1,内存调优

找到Tomcat根目录下的bin目录,设置catalina.sh文件中JAVA_OPTS变量即可,因为后面的启动参数会把JAVA_OPTS作为JVM的启动参数来处理。再说Java虚拟机的内存结构是有点复杂的,相信很多人在理解上都是很抽象的,它主要分为堆、栈、方法区和垃圾回收系统等几个部分组成,下面是我从网上扒的内存结构图:

内存调优这块呢,无非就是通过修改它们各自的内存空间的大小,使应用能够更加合理的运用,下图是我根据我机子的性能设置的参数,给各位详细解释一下各个参数的含义吧

1、-Xmx512m:设置Java虚拟机的堆的最大可用内存大小,单位:兆(m),整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m。堆的不同分布情况,对系统会产生一定的影响。尽可能将对象预留在新生代,减少老年代GC的次数(通常老年回收起来比较慢)。实际工作中,通常将堆的初始值和最大值设置相等,这样可以减少程序运行时进行的垃圾回收次数和空间扩展,从而提高程序性能。整编:微信公众号,搜云库技术团队,ID:souyunku

2、-Xms512m:设置Java虚拟机的堆的初始值内存大小,单位:兆(m),此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。

3、-Xmn170m:设置年轻代内存大小,单位:兆(m),此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。一般在增大年轻代内存后,也会将会减小年老代大小。

4、-Xss128k:设置每个线程的栈大小。JDK5.0以后每个线程栈大小为1M,以前每个线程栈大小为256K。更具应用的线程所需内存大小进行调整。

在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。

5、-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5 。

6、-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6。

7、-XX:MaxPermSize=16m:设置持久代大小为16m,上面也说了,持久代一般固定的内存大小为64m。

8、-XX:MaxTenuringThreshold=0:设置垃圾最大年龄。

如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。

如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。

2,垃圾回收策略调优

找到Tomcat根目录下的bin目录,也是设置catalina.sh文件中JAVA_OPTS变量即可。我们都知道Java虚拟机都有默认的垃圾回收机制,但是不同的垃圾回收机制的效率是不同的,正是因为这点我们才经常对Java虚拟机的垃圾回收策略进行相应的调整。下面也是通过我的一些需求来配置的垃圾回收策略:

Java虚拟机的垃圾回收策略一般分为:串行收集器、并行收集器和并发收集器。

串行收集器:

1、-XX:+UseSerialGC:代表垃圾回收策略为串行收集器,即在整个扫描和复制过程采用单线程的方式来进行,适用于单CPU、新生代空间较小及对暂停时间要求不是非常高的应用上,是client级别默认的GC方式,主要在JDK1.5之前的垃圾回收方式。

并发收集器:

1、-XX:+UseParallelGC:代表垃圾回收策略为并行收集器(吞吐量优先),即在整个扫描和复制过程采用多线程的方式来进行,适用于多CPU、对暂停时间要求较短的应用上,是server级别默认采用的GC方式。此配置仅对年轻代有效。该配置只能让年轻代使用并发收集,而年老代仍旧使用串行收集。整编:微信公众号,搜云库技术团队,ID:souyunku

2、-XX:ParallelGCThreads=4:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。

3、-XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0支持对年老代并行收集 。

4、-XX:MaxGCPauseMillis=100:设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。

5、-XX:+UseAdaptiveSizePolicy:设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开。

并发收集器:

1、-XX:+UseConcMarkSweepGC:代表垃圾回收策略为并发收集器。

好了,到此我对虚拟机的垃圾回收策略总结就这么多,还是这句话:优化的学习一直在路上,下面还有一张从其他博客中偷到的图,据说以上三种GC机制是需要配合使用的。

相关文章:

  • Java8 新特性
  • Java-并发编程--ThreadLocal、InheritableThreadLocal
  • 《LeetCode热题100》笔记题解思路技巧优化_Part_3
  • QT 状态机的使用
  • RocketMQ架构详解
  • 17个工作必备的Python自动化代码分享(上篇)
  • 泽众云真机-机型支持ADB调试功能即将上线
  • 进程学习--02
  • 有来团队后台项目-解析7
  • 鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Web)中篇
  • Postman请求API接口测试步骤和说明
  • C#使用SharpZipLib对文件进行压缩和解压
  • 【Linux】基础 IO(文件描述符)-- 详解
  • 爬蟲IP代理詳細指南
  • 【爬虫介绍】了解爬虫的魅力
  • canvas 五子棋游戏
  • Docker下部署自己的LNMP工作环境
  • java 多线程基础, 我觉得还是有必要看看的
  • js
  • PAT A1017 优先队列
  • SOFAMosn配置模型
  • tensorflow学习笔记3——MNIST应用篇
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 聚类分析——Kmeans
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 猫头鹰的深夜翻译:Java 2D Graphics, 简单的仿射变换
  • 前端性能优化——回流与重绘
  • 前端之React实战:创建跨平台的项目架构
  • 思考 CSS 架构
  • 小试R空间处理新库sf
  • 云大使推广中的常见热门问题
  • 栈实现走出迷宫(C++)
  • 移动端高清、多屏适配方案
  • ​比特币大跌的 2 个原因
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • #pragam once 和 #ifndef 预编译头
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (转载)Linux网络编程入门
  • ******IT公司面试题汇总+优秀技术博客汇总
  • .Net中间语言BeforeFieldInit
  • /etc/sudoers (root权限管理)
  • @angular/cli项目构建--Dynamic.Form
  • @RestControllerAdvice异常统一处理类失效原因
  • []FET-430SIM508 研究日志 11.3.31
  • []利用定点式具实现:文件读取,完成不同进制之间的
  • [2018/11/18] Java数据结构(2) 简单排序 冒泡排序 选择排序 插入排序
  • [Angular 基础] - 自定义指令,深入学习 directive
  • [BJDCTF 2020]easy_md5
  • [dart学习]第四篇:函数
  • [echarts] y轴不显示0
  • [Hadoop in China 2011] Hadoop之上 中国移动“大云”系统解析
  • [HAOI2016]食物链