配置优化
1.减少配置优化
option1:假设当前是rest应用(微服务),不需要jsp的情况
不需要静态资源,Tomcat容器有静态和动态
静态处理主要指DefaultServlet类,
优化方案:通过移除conf/web.xml中的org.apache.catalina.servlets.DefaultServlet
DefaultServlet:Tomcat处理静态资源的Servlet
动态处理主要指应用Servlet,JspServlet两个方面,应用servlet是由自己控制的,一般只有一个,如SpringMVC应用Servlet:DispatcherServlet
优化方案:通过移除conf/web.xml中的org.apache.jasper.servlet.JspServlet
JspServlet:编译并且执行jsp页面
如图是servlet和jsp的映射方式,*.jspx是强制用xml的方式输出jsp。
移除welcome-file-list
移除session设置或设置为-1(永不超时)
对于微服务或rest应用,不需要session,因为不需要状态。Session通过jsessionId进行用户跟踪,由于Http是无状态的,需要一个ID与当前用户会话联系,如Spring Session将HTTPSession的jsessionId作为类似于redis的key,实现多台机器登录,使用户会话不丢失。
存储jsessionId的方法:cookie,URL重写,SSL(安全认证)
文件的扩展名
移除Valve
Valve类似于filter
移除AccessLogValve,可以通过Nginx的Access Log替代,任何一个Valve实现都需要消耗java应用的计算时间。
option2:需要JSP的情况
此时jspServlet无法移除,就要通过源码去了解jspServlet类的实现原理。
Servlet生命周期:
实例化:Servlet和Filter实现类必须包含默认构造器,利用反射的方式进行实例化。
初始化:Servlet容器调用Servlet或Filter的init方法
销毁:Servlet容器关闭时,Servlet或者Filter的destroy()方法被调用
Servlet或者Filter在一个容器中,一般情况下在一个WebAPP中是一个单例,但也不排除应用会定义多个。比如在web.xml中可以这样定义:
对于spring来说,这就是两个不同的bean,在servlet中,当转发(forward)时有可能会跨越多个servlet。
JspServlet相关的优化
ServletConfig参数:
需要编译时:compiler,切换编译器
modificationTestInterval
不需要编译时:
Development=false,此时这些JSP就需要预编译了。
优化方法:ant task执行JSP编译
Maven插件,org.codehaus.mojo:jspc-maven-plugin
Jsp会翻译.jsp或者.jspx文件成.java,在编译成.class文件。
总结,conf/web.xml作为Servlet应用的默认web.xml,实际上,应用程序存在两份web.xml,其中包括Tomcat自己的conf/web.xml和应用的web.xml,最终将两者合并。
JspServlet如果development的参数为true,它会自动检查文件是否修改,如果修改重新翻译,再编译,加载,执行。JspServlet开发模式可能会导致OOM(内存溢出),卸载class不及时所导致perm区域不够。(class卸载时,需要将父类加载器设置为Null,当classLoader被GC后,父类加载器加载的class文件全部会被卸载掉)
配置调整
1.关闭自动重载
Reloadable默认是true,将其改为false即可。
2.修改连接线程池数量
2.1通过server.xml
程序中可以看出,实际的Tomcat接口是org.apache.catalina.Exector,扩展了J.U.C标准接口java.util.concurrent.Executor,在实现类中有具体的线程数量和线程池信息。
总结:Tomcat IO连接器使用的线程池实际是标准的java线程池的扩展,最大线程数量和最小线程数量实际上分别是源码中对应的MaximumPoolSize和CorePoolSize。
2.2使用jmeter工具
到底设置多少的线程数量才是最优?
首先,评估整体的数据量,假设100万QPS,有机器数量100台,每台支撑1万QPS,第二,进行压力测试,需要一些测试样本,jmeter来实现,1000线程发送请求,假设一次情况需要消耗10ms,1秒可以同时完成100个请求。100个线程最优。确保,Load不要太高,减少FullGC,GC取决于JVM堆的大小。执行一次操作需要5MB内存,50GB。20GB内存,必然要执行GC,要不调优程序,最后对象存储外化,如redis,同时又需要评估redis网络开销,又要评估网卡的接受能力。
第三,常规性压测,由于业务变更,会导致底层性能变化。
JVM优化
调整GC算法
如果java版本小于9,默认是PS MarkSweep,可选设置CMS,G1。
如果java9的话,默认是G1。