涨薪技术|0到1学会性能测试第53课-Tomcat配置

前面的推文我们掌握了Tomcat服务器的3种监控技术知识。今天给大家分享Tomcat调优技术。后续文章都会系统分享干货,带大家从0到1学会性能测试。

01Tomcat配置

当Tomcat服务器安装好并开始运行后,需要对服务器进行一些基本配置,通常关于Tomcat服务器的配置包括两部分:

第一:编辑Tomcat的XML配置文件;

第二:确定适当的环境变量;

1) XML配置文件

关于XML配置文件,Tomcat服务器有两个很重要的XML配置文件需要配置:server.xml和web.xml。通常情况下这两个文件存放Tomcat安装目录下的conf文件夹中。

server.xml文件是Tomcat最主要的配置文件,该文件主要是指定Tomcat启动时的初时配置,并定义Tomcat启动和构建的方式。server.xml文件中包含五类基本类别:顶层元素、连接器、容器、嵌套组件和全局设置。这些类别都有着很多属性,在配置过程中可以对这些值进行微调,通常包括以下几部分的内容:

顶层元素(Top Level Elements)

关于顶层元素主要包括服务器和服务两类,服务器主要定义一个单个的Tomcat服务器,主要包括Logger和ContextManager配置,此外还包括服务器支持的“端口”、“关机”和“类名”属性。服务则是一个元素,该元素嵌套在一个服务器中,服务包含一个或多个用于共享相同引擎的组件,该组件主要功能是定义一个单一服务器的组件,服务的名称在“name”属性中指定。

连接器(Connectors)

在服务器标签中可以定义一个或多个连接器,通过Catalina从这些端口向引擎组件发送请求,Tomcat允许定义HTTP和AJP两种连接器,关于这两种连接器将在连接器部分的内容中进行详细介绍。

容器(Containers)

这些元素使用Catalina直接处理设备的请求。

上下文(Context)

此元素是一个单一的web应用,并且包含如果查找到最适合的应用程序资源的路径信息,当Catalina接收到一个请求后,它使用context去匹配最长的URL,直到找到正确的服务请求元素,context元素为每个元素设置一个最大的嵌套实例,虽然可以通过修改server.xml文件来修改context的内容,但一般情况下不应该修改context内容,因为这些配置如果不重启Tomcat服务器不能被加载。

主机(Host)

这个元素嵌套在引擎元素中,用于关联Catalina服务器所在网络中的网络服务器名,这个元素的功能只有在虚拟机注册DNS管理域的过程中才能正确使用,该元素最大的作用是嵌套别名,可以为同一个虚拟机定义多个不同的别名。

集群(Cluster)

集群元素能够提供上下文属性复制、WAR部署、会话复制并且将其嵌套在一个引擎或主机元素中,虽然可以对这个元素进行配置,但一般情况下缺省设置就可以满足用户的需求。

全局命名资源(Global Naming Resources)

这个元素主要是为一个指定服务器指定全局Java名和目录接口资源,可以在该元素中定义和的查找特征并且可以使用进行链接。如果使用该技术定义其它的参数,那么必须指定和配置对象属性。

范围(Realm)

这个元素可以被嵌套在任何容器元素中,用于定义数据库用户名、密码和容器的角色,如果嵌套在主机或引擎元素中,那么Realm元素的特征将会继承低级别容器的特性。Realm元素中最生要的属性是“classmate”,其主要提供不同类型容器的安全性,并且实现的方式有多种。

资源(Resources)

这个元素主要是用于通过web应用程序引导Catalina的静态资源,常见的静态资源有:类、HTML和JSP文件等。

Web.xml文件

Web.xml文件遵从Servlet规范,其主要包含的信息用于部署和配置web应用程序,如果是第一次配置Tomcat,那么主要是定义Servlet映射到主要的部件(如JSP)。在Tomcat中,这个文件以同样的方式在Servlet规范中描述这些功能。

2) 环境变量

在第一次配置Tomcat时,有几个环境需要进行适当的修改,主要包括:JAVA_OPTS、CATALINA_HOME、CATALINA_OPTS。

JAVA_OPTS

使用该变量可以定义JVM中堆的大小,堆大小是一个很重要的指标,当在部署一个新的应用程序时,需要设置一个适当的堆大小的值,否则会影响系统性能,同时可以消除或减小OOME消息。

CATALINA_HOME

该变量用于指定Tomcat的安装位置,当Tomcat脚本启动时会自动去检查这个变量的值,以确定设置是否正确,避免运行过程中出现问题。

CATALINA_OPTS

该变量用于设置Tomcat指定的不同的选项。

除了以上一些配置外,还有两个相关的配置会影响系统性能:DNS查找和JSP编译。

DNS查找

如果web应用服务器需要获得客户端的日志信息,那么通常有两种方式:

一是:记录客户端机器的IP地址;

二是:在DNS中查找客户端主机名信息;

而DNS查询需要网络流量,在查询过程中可能会经历多个服务器的往返查找,但也可能不需要,这样就会导致出现延迟响应的情况,如果需要消除这些延迟响应,就必须关闭DNS查询,在HTTP对象中有一个getRemoteHost的方法,通过这个方法可以找到一个唯一的IP地址,关于DNS的选项设置在server.xml文件中的connector(连接器)中设置,源代码如下:

<!--   Define a non-SSL Coyote HTTP/1.1 Connector on port 8080 --><Connector     className="org.apache.coyote.tomcat4.CoyoteConnector"    port="8080" minProcessors="5" maxProcessors="75"    enableLookups="true" redirectPort="8443"    acceptCount="10" debug="0" connectionTimeout="20000"    useURIValidationHack="false" />

如果需要关闭DNS查找,那么将该选项设置为“false”。除非需要指定一个完整的主机名去访问网站,否则都需要将该选项设置为“false”,这样不但可以节约带宽、查找时间和内存。当然对于低流量的网站,这个设置项可能不会有明显的效果,但是不能排除它某天变成了一个高流量的网站。

JSP编译

在一个JSP页面第一次被访问时,它需要转换为Java servlet源码,并且编译在JAVA字节码,而当许多不同用户同时访问JSP页面时,服务器可能会被处于一种高负载状态,所以应该改善网站对JSP页面的处理方法,进而优化JSP的性能。

1) Tomcat如何处理JSP页面

JSP是Java servlet代码与HTML标记的组合,Tomcat处理JSP是使用一个称为Jasper 2的引擎,该引擎包括各种处理和解析JSP的组件,以及JSP的编译器。在一个JSP页面第一次被访问时,Jasper引擎会将源码转换为Java servlet源码,并且使用JAVA编译器将其编译成JAVA字节码。

2) 审核动态内容

JSP性能改进的第一步是采取分析网站的结构、预期负载和JSP页面需要实现的功能,如果创建的网站中混杂着动态和静态,当网站可以完成定期更新静态内容时,那么应该是动态处理结束后才多的去处理静态内容,例如网站的标题,这是一个动态的内容,但是一天可能才处理一两次。

现在解决动态审核问题不完全是使用,现在有一些开源于JAVA模板来解决这个问题(如Velocity或Freemarker),在未来可能会成为一个新的功能。

3) JSP预编译技术

当服务器运行JSP页面时服务器会使用最大的性能来编译JSP页面,如果缓解这一问题,一般会对JSP进行预编译操作,而不是等运行时才进行实时的编译。通常有以下三种预编译的方法来提高系统的性能。

第一:使用请求进行预编译

预编译的一次最简单的方法是,在发送请求的过程中进行预编译,因为在第一次发送请求时,JSP会自动进行编译,这样在第一个真实的用户访问该JSP页面时就不需要再编译了,如果只少数JSP页面,并且不需要频繁的启动服务器,这样可以在服务器启动时,使用一个小脚本自动爬行所有的JSP页面,这样可以大大的提高性能。这个方法在开发过程中很有用,因为这种方法可以查找是那些用户第一时间访问JSP页面,并且可以纠正一些错误。

第二:启动时进行预编译

JAVA中有一个Java servlet的模块,它包括JSP指定的一些功能和语法元素,这些语法在Web应用程序启动时会指定JSP进行编译,在“WEB-INF/web.xml”文件中可以对JSP进行预编译设置,如以下实例:

<web-app ...> <servlet>  <servlet-name> YourJSP.jsp </servlet-name>  <jsp-file> /path/to/yourjsp.jsp </servlet-name>  <load-on-startup> 1 </load-on-startup> </servlet>  </web-app>

整数“1”是用来指定编译序顺的,所以可以为预编译创建一个层次结构,这样可以消除第一个用户访问预编译页面的时间延迟,降低web程序重启的所需要的资源。

第三:在编译过程中进行预编译

在编译过程中进行预编译是指在构建Web应用程序时,使用JspC进行预编译JSP代码,而不是在Tomcat服务器上进行动态编译,在一些情况中下这种技术可以提高4%的系统性能。

JSP最佳实践

前面介绍了通过修改Tomcat配置文件来提高JSP性能,而遵守一些编码规则也可以提高JSP的性能,通常有两种方法:高效缓存和对象控制。

第一:在代码中如何有效提高JSP原始的缓存数据可以有效的提高性能,即如何有效的利用缓存中的数据或如何高效使用缓存方法来处理数据。

第二:目标控制,主要包括会话长度/范围、线程池配置和缓存区大小。

1) JSP数据缓存

如果JSP页面已经产生了一些静态或动态内容,那么这种情况不要它再出现,因为它可以通过会话或应用程序调用缓存数据,为了得到安全的动态内容,这样会重复使用所有活动会话。

生成静态文件使用了一次_jsplnit()方法,同时使用_jspService方法对数据进行备份,但不在每次请求页面时使用out.print()。缓存中的动态数据有4个持久机制,Tomcat原始的持久机制、cookies、URL重写和隐藏区域。

通常的一个解决方案是,平衡客户端和服务器间的负载、安全缓存(Tomcat持续支持安全的存储数据)和处理隐藏区域。

2) 对象控制

在关闭会话、重新使用标签和配置缓存区时,很容易浪费服务器CPU时间周期,特别是在清理JSP代码时需要考虑这个问题,所以可以考虑移除大数据和关闭会话、对象。在整个页面生成过程中一次性移除大数据(如图片),通常使用flush()方法移除,并且应该考虑设置缓存大小。在控制对象时,JSP包括处理会话、孤立对象和饥饿内存的处理机制,如超时和序列化。

02连接器配置

接连器元素是Tomcat用于连接外部程序的,其允许Catalina接受请求,传送到Web应用程序,将生成的动态信息通过连接器返回到Tomcat服务器。

Tomcat的连接器包括两种:HTTP和AJP。

每个连接器元素都有一个端口,Tomcat会通过这个端口来监听请求,并且会为服务器和引擎中的连接器元素设置等级,这样管理员可以通过创建逻辑结构来管理这些数据流。此外,用户的请求通过路由器可以找到相应的服务器,连接器通过连接可以将Tomcat与其它web技术进行连接(如Apache服务器),这样可以有效平衡负载。

连接器元素只有一件事,就是监听请求,并通过引擎获得指定端口上返回的结果。就它本身来说,这个连接器自身没什么功效,这个元素包含的唯一信息是输入和输出的端口,以及一些告诉它如何准确输入和输出的特性。

那么如何通过嵌套连接器来实现我们需要的功能呢?下面是一个例子:​​​​​​​

<Server>  <Service>    <Connector port="8443"/>    <Connector port="8444"/>    <Engine>      <Host name="yourhostname">        <Context path="/webapp1"/>        <Context path="/webapp2"/>      </Host>    </Engine>  </Service></Server>

上例中定义了两个连接元素,监听的两个端口号为8443和8444,但需要注意的是每个操作系统每个连接器只允许一个端口,所以每个边接器需要为自己定义一个指定的端口。并且这两个连接器元素都嵌套在一个服务器元素中,这样可以告诉连接器如何监听指定的端口,并且通过服务器的引擎连接器可以处理这些请求并将处理后的结果返回到连接器。

根据该例设置,这两个连接器都是使用相同的引擎发送请求,同样反过来,也是通过这个引擎来获得Web应用程序返回的结果。

如果现在想修改当前配置,不需要每个连接器返回的请求有两个响应,只需要每个连接器返回其指定的端口信息,要实现该功能,只要对配置进行如下修改即可:​​​​​​​

<Server>  <Service name="Catalina">    <Connector port="8443"/>    <Engine>      <Host name="yourhostname">        <Context path="/webapp1"/>      </Host>    </Engine>  </Service>  <Service name="Catalina8444">    <Connector port="8444"/>    <Engine>      <Host name="yourhostname">        <Context path="/webapp2"/>      </Host>    </Engine>  </Service></Server>

该例中使用了两个不同的服务,使用两个不同的连接器,通过连接器中两个不同端口和引擎连接到同一台服务器,虽然变的复杂了,但是层次结构更简单。

HTTP连接器

虽然Tomcat设计了一个servlet容器,但其它功能只能适用于一个独立的Web服务器,而servlet容器的这些功能HTTP连接器也可以实现。HTTP连接器使用HTTP/1.1协议,它代表一个单独的连接器组件,监听一个给定的服务器上指定的TCP端口的连接。

连接器有很多属性,通过修改之些属性可以精确的指定它的功能,并且可以对功能进行受权,如代理和重定向。其两个最重要的属性是“协议”和“SSLEnabled”。

“协议”属性主要定义连接器使用的通信协议,默认的通信协议为HTTP/1.1,但可以对通信协议进行修改,并且允许设置更多的其它的协议。例如,希望调整socket的性能,可以将“协议”属性项设置为NIO(Java New IO简称)协议。如果将“SSLEnabled”属性设置为“True”连接器会使用SSL握手、SSL加密和SSL解密。

HTTP连接器也可以作用为负载均衡的一种解决方案,配合HTTP负载平衡器可以支持粘性会话,如mod_proxy方法,但是如果处理代理的情况AJP连接器比HTTP连接器效果更好。

AJP连接器

AJP连接器的工作方式与HTTP连接器的方式一样,但其使用的协议为AJP协议,Apache JServ协议或AJP协议,AJP协议是一个优化的二进制版本的协议,通常用于Tomcat服务器与Apache Web应用程序进行通讯。

AJP连接器通常使用在Tomcat的插件技术mod_jk中,也可以重新已无效的mod_jserv插件,并且通常JK库函数可以支持更多的协议和Tomcat的指定功能。AJP连接器功能通常需要一个高流量的系统支持,通常是集群的web系统。其允许Apache服务器提供静态内容和代理请求,目的是让整个网络负载更平均,这样可以让Tomcat服务器更专注于处理动态内容。

Connerctor参数配置

以下代码是连接器配置的一个实例:​​​​​​​

<Connector executor="tomcatThreadPool"               port="80" protocol="HTTP/1.1"               connectionTimeout="50000"               keepAliveTimeout="20000"               maxKeepAliveRequests="1"               redirectPort="444"               maxHttpHeaderSize="8192" URIEncoding="UTF-8" enableLookups="false" acceptCount="100" disableUploadTimeout="true"/>

常见连接器参数如下:

connectionTimeout:网络连接超时时间,单位为毫秒,如果设置为“0”则表示永不超时,不建议这样设置;

keepAliveTimeout:保持连接的最长时间,单位为毫秒;

maxKeepAliveRequests:最大的连接数(“1”表示禁用该设置,“-1”表示不限制个数,缺省值为100);

maxHttpHeaderSize:表示允许的HTTP请求头的最大值,超过此大小的请求将不予受理;

URIEncoding:设置Tomcat容器的URL编码格式;

acceptCount:指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理,默认为10个;

disableUploadTimeout:上传文件时是否使用超时机制;

enableLookups:是否启动反查域名机制(取值为true或false),为了提高处理能力,应设置为false;

bufferSize:定义连接器所提供的输入流中缓存区大小,缺省值为2048个字节;

maxSpareThreads:最大空闲连接数,如果创建的线程超过这个值,Tomcat就会关闭不再需要的线程数,缺省值为50;

maxThreads:最多同时处理的连接数,Tomcat使用线程来处理接收的每个请求,这个值表示Tomcat可创建的最大的线程数;

minSpareThreads:最小空闲线程数,Tomcat初始化时创建的线程数,该值应该少于maxThreads,缺省值为4;

minProcessors:最小空闲连接线程数,缺省值为10;

maxProcessors:最大连接线程数,默认值为75;

下面详细介绍maxThreads、connectionTimeout和acceptCount这个参数:

一、maxThreads配置

maxThreads代表Tomcat的HTTP连接器所创建的请求处理线程的最大数目,如以下代码:​​​​​​​

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"        maxThreads="250" minSpareThreads="20" maxIdleTime="60000" /><Connector executor="tomcatThreadPool"               port="80" protocol="HTTP/1.1"               connectionTimeout="60000"               keepAliveTimeout="15000"               maxKeepAliveRequests="1"               redirectPort="443"               ....../>

如上例表示Tomcat服务器最大榀以处理250个请求,如果不设置该值,那缺省值为200。

maxThreads处理过程如下:

1) 当服务器启动时,HTTP连接器将创建一个基础线程数,这个值为minSpareThreads(最小空闲连接数);

2) 每个传入的请求都需要一个持续时间,允许的最大时间为keepAliveTimeout所设置的值;

3) 如果需要同时处理的请求数超过minSpareThreads设置的值,那么额外的线程数将以最大配置数为准,即maxThreads的值;

4) 如果同时处理的请求数超过最大配置值,即超过maxThreads所设置的值,那么这么请求将会排成队列,队列最大值由acceptCount确定;

5) 如果队列长度超过acceptCount所设置的值,那么请求连接时将会被拒绝,直到有可用资源时才建立连接;

maxThreads是一个很重要的参数,那么在配置过程它应该遵守什么原则呢?

org.apache.tomcat.util.threads.ThreadPool logFull SEVERE: All threads (150) are currently busy, waiting. Increase maxThreads (150) or check the servlet status

如果出现上述的错误,那么首先需要调查请求所花费的时间,并检查它是否返回线程池,例如,数据库连接一直不释放,那么线程需要等获得数据库连接后才能运行,这样导致其它的请求不能被处理,如果此时增大maxThreads值,可以会导致以下后果:

–消耗大量内存;

–在切换上下文内容时所花费的时间将会进一步增多;

这些元素使用Catalina直接处理设备的请求。

所以,如果在优化系统性能过程中,将该设置高达500-750了,那么这样将带来上述两个问题,所以maxThreads的值大于750,那么则需要使用Tomcat服务器集群来解决这个问题,如需要将maxThreads的值设置为1000,那么需要使用两个Tomcat服务器,各自设置为500,而不是将一个Tomcat服务器设置为500。

connectionTimeout配置

connectionTimeout用于设置网络连接超时时间。设置通讯的超时时间对于改善通讯过程非常重要,它可以帮助发现问题和稳定分布系统,JK有几种不同的超时类型,按属性分,通常包括:CPing/CPong、低级别TCP超时、连接池和空闲超时、防火墙连接和回复超时,通常在httpd.conf、workers.properties和server.xml三个文件中进行设置,也可以分别对这些选项进行设置。但这些选项默认情况是禁用状态,一般不设置超时的极端值,否则可能适得其反。

1) CPing/CPong

CPing/CPong用于测试后端小数据包的状态,在建立连接后和请求返回数据包之前JK可以直接测试数据包,可以通常配置来设置CPong与CPing之间最大空闲时间。

在ping_mode模块中可以设置不种连接方式的超时时间:

连接模式(connect mode):使用connect_timeout属性设置超时时间;

前岗模式(prepost mode):使用prepost_timeout属性设置超时时间;

间隔模式(interval mode):使用connection_ping_interval属性设置空闲间隔时间;

2) 低级别TCP超时

一些平台允许设置TCP套接字操作超时,这种情况只允许在Linux和Windows操作系统中使用,其它的平台不支持,如果平台TCP发送和接受超时,那么可以通过socket_timeout属性进行设置,该属性在文件workers.properties中。如果平台不支持套接字操作超时,JK也会接受这个属性,但这种情况下,该属性没有任何效果,缺省值为“0”,表示禁用超时,该属性的单位为秒,而非毫秒,这个超时是一个低层次的,用于套接字中每个读与写的操作。

使用此属性JK可以很快的反应关于网络类型的问题,但这也有一些负影响,因为平台太多,如果真的是由于网络问题引起的超时,或者没有收到后端返回的数据包,那么JK不可能很快的恢复,故不可能将这个值设置的太小。

一般情况下当建立连接后,可以使用socket_connect_timeout来测试超时时间,其单位为毫秒,因为一些平台不支持socket_timeout,超时时间一般设置为1000至5000毫秒。

3) 连接池和空闲超时

JK会处理每个Web服务器连接池中的每个连接,会连接被用于持久模式,当一个请求处理完成后,连接会处于断开状态,等待下一个发送过来的请求,连接池希望增加并行请求的数量。

大多数应用程序每个时间段所承受的负载是有所不同的,所以当连接数在不断的增加时,连接会被临时保存在后端,这样导致前端越来越拥挤,所以后端可能会使用一个线程来处理提交的新的连接,所以如果当系统负载减少时可以将连接池缩小。

JK允许在连接池的一些连接在一些空闲时间后被关闭,使用connection_pool_timeout属性可以设置最大空闲时间,单位为秒,其缺省值为“0”,表示禁止关闭空闲连接。一般建议设置为10分钟,即600秒。如果需要设置此属性,那么在Tomcat服务器中server.xml配置文件中的AJP连接器中修改connectionTimeout选项,单位为毫秒。

JK并不会立即关闭那些超时的连接,而是先运行一些内部自动维护的任务,每隔60秒自动检查所有空闲状态的连接,60秒的时间间隔可以使用全局属性(worker.maintain)进行重新设置,但不建议修改该值。

4) 防火墙连接

空闲连接来自于防火墙,这往往是在网络服务器和后端之间,如果连接长时间处于闲置状态,那么连接的状态表将会丢失,TCP是一个可靠的协议,它会检测TCP ACKs是否丢失,并且会重新发送那些时间相对较长的包,当然这一般需要几分钟的时间。因此JK配置时常常需要配置connection_pool_timeount

和connection_pool_minsize两个属性,Tomcat测试需要配置connectionTimeout属性来防止空闲连接下降。

另外,使用可以配置socket_keepalive标准套接字选项,这样当连接处于空闲状态时,会自动向每个连接发送TCP keepalive包,缺省值为“False”,如果怀疑是防火墙引用的空闲连接,那么可以将该选项设置为“True”。但是对于不同的平台,默认的时间间隔和算法是不一致的,所以要调整TCP的设置项来测试其控制TCP keepalive的效果。

5) 回复超时

对于请求的响应JK也可能出现超时的情况,出现超时的响应不能被处理,反之一样,连接响应的数据包需要多长时间才能完成,这是我们关注的问题,例如一个长时间的下载,无法设置一个全局的回复超时的时间,因为无法确定最后下载的时间。

通过设置replay_timeout属性可以设置超时时间,单位为毫秒,缺省值为“0”,表示不禁用超时,如以下配置:​​​​​​​

worker.worker1.port = 8888worker.worker1.reply_timeout = 120000worker.worker1.socket_timeout = 150000

该配置在workers.properties文件中设置。

配合Apache一起使用时,可以通过设置http的环境变量reply_timeout来设置超时时间,这样更灵活。

acceptCount配置

acceptCount是指当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理,默认为10个,即允许请求队列的最大长度,如果客户端提交的请求不能被同时并发处理完成,即客户端请求数超过maxThreads的值,那么其余的请求将会以队列的方式存储着,如果这个队列的长度大于acceptCount所设置的值,那么客户端提交的请求就不会被处理,即被服务器拒绝,导致连接失败。

在设置该值时应该注意,这个值不能设置的太小也不能设置的太大,如果设置的太小会出现大量请求可能被直接拒绝的情况,但其它此时这些请求可能根本没有超时;如果将该值设置的过大,则会出现请求被超时的情况,因为如果排的队列过长,这样后面的队列很可能出现超时的情况,keepAliveTimeout和connectionTimeout两个属性值会影响决定连接是否超时,如果队列过长后面的请求就会出现超时,这样请求同样也无法被正确的处理,所以在设置该值时,需要以服务器访问的峰值或平均值来衡量,但实际测试过程中可以通过配置该值来测试性能的表现。

下期分享APR配置,敬请关注!

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容