springbootJava web

tomcat性能优化

2020-01-05  本文已影响0人  WEIJAVA

Tomcat性能指标:吞吐量、响应时间、错误数、线程池、CPU 、内存等。
使用jmeter进行压测,然后观察相关指标

使用命令查看相关指标
01 查看tomcat进程pid
ps -ef | grep tomcat

02 查看进程的信息
cat /pro/pid/status

03 查看进程的cpu和内存
top -p pid

使用工具查看相关指标
jconsole、jvisualvm、arthas、psi-probe等

优化思路

conf/server.xml核心组件

conclusion:Connector and Context

conf/server.xml非核心组件

官网 :https://tomcat.apache.org/tomcat-8.0-doc/config/index.html

<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> <!--监听内存溢出--> 
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> 
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> 
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<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>
<Valve className="org.apache.catalina.valves.AccessLogValve"
 directory="logs"
 prefix="localhost_access_log" suffix=".txt" 
pattern="%h %l %u %t &quot;%r&quot; %s %b" />
<Realm className="org.apache.catalina.realm.LockOutRealm"> 
<!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. --> 
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
 </Realm>

conf/web.xml

全局的web.xml文件有些标签用不到的,可以删除掉。

JVM层面

因为Tomcat运行起来本身就是一个Java进程,所以这块可以参照JVM部分的优化思路。

配置优化

减少web.xml/server.xml中标签

最终观察tomcat启动日志[时间/内容],线程开销,内存大小,GC等

<servlet>
  <servlet-name>default</servlet-name> 
  <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
   <init-param> 
    <param-name>debug</param-name> 
    <param-value>0</param-value>
   </init-param>

   <init-param> 
    <param-name>listings</param-name>
     <param-value>false</param-value> 
  </init-param> 

  <load-on-startup>1</load-on-startup> 
</servlet> 

<servlet-mapping>
   <servlet-name>default</servlet-name> 
  <url-pattern>/</url-pattern>
 </servlet-mapping>
<servlet> 
    <servlet-name>jsp</servlet-name>
   <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> 
  
  <init-param>
     <param-name>fork</param-name> 
    <param-value>false</param-value>
     </init-param> 

    <init-param> 
      <param-name>xpoweredBy</param-name>
      <param-value>false</param-value> 
    </init-param> 

    <load-on-startup>3</load-on-startup> 
</servlet>
<servlet-mapping>
     <servlet-name>jsp</servlet-name> 
     <url-pattern>*.jsp</url-pattern>
     <url-pattern>*.jspx</url-pattern>
</servlet-mapping>
<welcome-file-list> 
    <welcome-file>index.html</welcome-file>
     <welcome-file>index.htm</welcome-file> 
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<mime-mapping> 
    <extension>123</extension>
     <mime-type>application/vnd.lotus-1-2-3</mime-type>
     </mime-mapping> <mime-mapping> 
    <extension>3dml</extension> 
    <mime-type>text/vnd.in3d.3dml</mime-type>
</mime-mapping>
<session-config>
     <session-timeout>30</session-timeout>
</session-config>

调整优化server.xml中标签

1.Connector标签

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

对于protocol="HTTP/1.1",查看源码
构造函数

public Connector(String protocol) { setProtocol(protocol); }

setProtocol(protocol)因为配置文件中传入的是HTTP/1.1 并且这里没有使用APR

    else  {
        if ("HTTP/1.1".equals(protocol)) {
            setProtocolHandlerClassName("org.apache.coyote.http11.Http11NioProtocol");
        } else if ("AJP/1.3".equals(protocol)) {
            setProtocolHandlerClassName("org.apache.coyote.ajp.AjpNioProtocol");
        } else if (protocol != null) {
            setProtocolHandlerClassName(protocol);
        }
    }

发现这里调用的是Http11NioProtocol,也就是说明tomcat8.0.x中默认使用的是NIO使用同样的方式看tomcat7和tomcat8.5,你会发现tomcat7默认使用的是BIO,tomcat8.5默认使用的是NIO

针对BIO和NIO的方式进行压测
(1)BIO
来到tomcat官网Configuration/HTTP/protocol

org.apache.coyote.http11.Http11Protocol - blocking Java connector 
org.apache.coyote.http11.Http11NioProtocol - non blocking Java NIO connector 
org.apache.coyote.http11.Http11Nio2Protocol - non blocking Java NIO2 connector 
org.apache.coyote.http11.Http11AprProtocol - the APR/native connector.

(2)NIO
tomcat8.0中默认使用的是NIO
(3)APR
调用本地方法库进行IO操作

executor属性
最佳线程数公式 :((线程等待时间+线程cpu时间)/线程cpu时间) * cpu数量
默认的可以查看StandardExecutor类
设置一些属性
官网:https://tomcat.apache.org/tomcat-8.0-doc/config/http.html
(1)acceptCount:达到最大连接数之后,等待队列中还能放多少连接,超过即拒绝,配置太大也没有意义
(2)maxConnections
达到这个值之后,将继续接受连接,但是不处理,能继续接受多少根据acceptCount的值
BIO:maxThreads
NIO/NIO2:10000 ——— AbstractEndpoint.maxConnections
APR:8192
(3)maxThreads:最大工作线程数,也就是用来处理request请求的,默认是200,如果自己配了executor,并且和Connector有关联了,则之前默认的200就会被忽略,取决于CPU的配置。监控中就可以看到所有的工作线程是什么状态,通过监控就能知道开启多少个线程合适
(4)minSpareThreads
最小空闲线程数
可以实践一下,Connector配合自定义的线程池

<Connector executor="tomcatThreadPool" port="8080" 
protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" 
maxThreads="150" minSpareThreads="4"/>

其实这块最好的方式是结合BIO来看,因为BIO是一个request对应一个线程
值太低,并发请求多了之后,多余的则进入等待状态。 值太高,启动Tomcat将花费更多的时间。 比如可以改成250。

2.Host标签

autoDeploy :Tomcat运行时,要用一个线程拿出来进行检查,生产环境之下一定要改成false

3.Context标签

reloadable:false

reloadable:如果这个属性设为true,tomcat服务器在运行状态下会监视在WEB-INF/classes和WEB-INF/lib目录下 class文件的改动,如果监测到有class文件被更新的,服务器会自动重新加载Web应用。 在开发阶段将reloadable属性设为true,有助于调试servlet和其它的class文件,但这样用加重服务器运行负荷,建议 在Web应用的发存阶段将reloadable设为false。

启动速度优化

<Host startStopThreads="0"> </Host>

其他方面的优化

常见问题排查

上一篇 下一篇

猜你喜欢

热点阅读