接连器元素是Tomcat用于连接外部程序的,其允许Catalina接受请求,传送到Web应用程序,将生成的动态信息通过连接器返回到Tomcat服务器。Tomcat的连接器包括两种:HTTP和AJP。
每个连接器元素都有一个端口,Tomcat会通过这个端口来监听请求,并且会为服务器和引擎中的连接器元素设置等级,这样管理员可以通过创建逻辑结构来管理这些数据流。此外,用户的请求通过路由器可以找到相应的服务器,连接器通过连接可以将Tomcat与其它web技术进行连接(如Apache服务器),这样可以有效平衡负载。
连接器元素只有一件事,就是监听请求,并通过引擎获得指定端口上返回的结果。就它本身来说,这个连接器自身没什么功效,这个元素包含的唯一信息是输入和输出的端口,以及一些告诉它如何准确输入和输出的特性。
那么如何通过嵌套连接器来实现我们需要的功能呢?下面是一个例子:
上例中定义了两个连接元素,监听的两个端口号为8443和8444,但需要注意的是每个操作系统每个连接器只允许一个端口,所以每个边接器需要为自己定义一个指定的端口。并且这两个连接器元素都嵌套在一个服务器元素中,这样可以告诉连接器如何监听指定的端口,并且通过服务器的引擎连接器可以处理这些请求并将处理后的结果返回到连接器。
根据该例设置,这两个连接器都是使用相同的引擎发送请求,同样反过来,也是通过这个引擎来获得Web应用程序返回的结果。
如果现在想修改当前配置,不需要每个连接器返回的请求有两个响应,只需要每个连接器返回其指定的端口信息,要实现该功能,只要对配置进行如下修改即可:
该例中使用了两个不同的服务,使用两个不同的连接器,通过连接器中两个不同端口和引擎连接到同一台服务器,虽然变的复杂了,但是层次结构更简单。
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服务器更专注于处理动态内容。
以下代码是连接器配置的一个实例:
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代表Tomcat的HTTP连接器所创建的请求处理线程的最大数目,如以下代码:
maxThreads="250" minSpareThreads="20" maxIdleTime="60000" />
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 = 8888
worker.worker1.reply_timeout = 120000
worker.worker1.socket_timeout = 150000
该配置在workers.properties文件中设置。
配合Apache一起使用时,可以通过设置http的环境变量reply_timeout来设置超时时间,这样更灵活。
acceptCount配置
acceptCount是指当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理,默认为10个,即允许请求队列的最大长度,如果客户端提交的请求不能被同时并发处理完成,即客户端请求数超过maxThreads的值,那么其余的请求将会以队列的方式存储着,如果这个队列的长度大于acceptCount所设置的值,那么客户端提交的请求就不会被处理,即被服务器拒绝,导致连接失败。
在设置该值时应该注意,这个值不能设置的太小也不能设置的太大,如果设置的太小会出现大量请求可能被直接拒绝的情况,但其它此时这些请求可能根本没有超时;如果将该值设置的过大,则会出现请求被超时的情况,因为如果排的队列过长,这样后面的队列很可能出现超时的情况,keepAliveTimeout和connectionTimeout两个属性值会影响决定连接是否超时,如果队列过长后面的请求就会出现超时,这样请求同样也无法被正确的处理,所以在设置该值时,需要以服务器访问的峰值或平均值来衡量,但实际测试过程中可以通过配置该值来测试性能的表现。