Keep-Alive功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。市场上 的大部分Web服务器,包括iPlanet、IIS和Apache,都支持HTTP Keep-Alive。对于提供静态内容的网站来说,这个功能通常很有用。但是,对于负担较重的网站来说,这里存在另外一个问题:虽然为客户保留打开的连 接有一定的好处,但它同样影响了性能,因为在处理暂停期间,本来可以释放的资源仍旧被占用。当Web服务器和应用服务器在同一台机器上运行时,Keep-Alive功能对资源利用的影响尤其突出。 此功能为HTTP 1.1预设的功能,HTTP 1.0加上Keep-Alive header也可以提供HTTP的持续作用功能。 
Keep-Alive: timeout=5, max=100 
timeout:过期时间5秒(对应httpd.conf里的参数是:KeepAliveTimeout),max是最多一百次请求,强制断掉连接 
就是在timeout时间内又有新的连接过来,同时max会自动减1,直到为0,强制断掉。 
Tomcat中的相关设置,在server.xml 中的Connector 元素中。 
keepAliveTimeout: 
此时间过后连接就close了,单位是milliseconds 
maxKeepAliveRequests: 

最大长连接个数(1表示禁用,-1表示不限制个数,默认100个。一般设置在100~200之间). 


maxKeepAliveRequests="1"就可以避免tomcat产生大量的TIME_WAIT连接,从而从一定程度上避免tomcat假死


HTTP 持久连接 
持久连接(Keep-Alive)也叫做长连接,它是一种 TCP 的连接方式,连接会被浏览器和服务器所缓存,在下次连接同一服务器时,缓存的连接被重新使用。由于 HTTP 的无状态性,人们也一直很清楚“一次性”的 HTTP 通信。持久连接则减少了创建连接的开销,提高了性能。HTTP/1.1 已经支持长连接,大部分浏览器和服务器也提供了长连接的支持。 
可以想象,要想发起长连接,服务器和浏览器必须共同合作才可以。一方面浏览器要保持连接,另一方面服务器也不会断开连接。也就是说要想建立长连接,服务器和浏览器需要进行协商,而如何协商就要靠伟大的 HTTP 协议了 

浏览器在请求的头部添加 Connection:Keep-Alive,以此告诉服务器“我支持长连接,你支持的话就和我建立长连接吧”,而倘若服务器的确支持长连接,那么就在响应头部添加“Connection:Keep-Alive”,从而告诉浏览器“我的确也支持,那我们建立长连接吧”。服务器还可以通过 Keep-Alive:timeout=10, max=100 的头部告诉浏览器“我希望 10 秒算超时时间,最长不能超过 100 秒”。 
在 Tomcat 里是允许配置长连接的,配置 conf/server.xml 文件,配置 Connector 节点,该节点负责控制浏览器与 Tomcat 的连接,其中与长连接直接相关的有两个属性,它们分别是:keepAliveTimeout,它表示在 Connector 关闭连接前,Connector 为另外一个请求 Keep Alive 所等待的微妙数,默认值和 connectionTimeout 一样;另一个是 maxKeepAliveRequests,它表示 HTTP/1.0 Keep Alive 和 HTTP/1.1 Keep Alive / Pipeline 的最大请求数目,如果设置为 1,将会禁用掉 Keep Alive 和 Pipeline,如果设置为小于 0 的数,Keep Alive 的最大请求数将没有限制。也就是说在 Tomcat 里,默认长连接是打开的,当我们想关闭长连接时,只要将 maxKeepAliveRequests 设置为 1 就可以。 


   其中: 
keepAliveTimeout:表示在下次请求过来之前,tomcat保持该连接多久。这就是说假如客户端不断有请求过来,且为超过过期时间,则该连接将一直保持。 

maxKeepAliveRequests:表示该连接最大支持的请求数。超过该请求数的连接也将被关闭(此时就会返回一个Connection: close头给客户端)。


https://yq.aliyun.com/articles/2779?spm=5176.100239.yqblog1.98.C140OT 
前提说明 
为了确保服务不会被过多的http长连接压垮,我们需要对tomcat设定个最大连接数,超过这个连接数的请求会拒绝,让其负载到其它机器。达到保护自己的同时起到连接数负载均衡的作用。 

动手去做 
一开始根据故障todoList提供的参数MaxKeepAliveRequests,进行验证,我们将tomcat配置server.xml修改为: 
screenshot 
同时,启动客户端模拟30个长连接。 

预期应该只有10个连接能保持住。 
结果与预期不符,30个连接都连上了,而且正常。 
这由此怀疑提供的配置参数是否是真正限制最大连接数的含义了。 
screenshot 
KeepAlive是在HTTP1.1中定义的,用来保持客户机和服务器的长连接,通过减少建立TCP Session的次数来提高性能。常用的配置参数有{KeepAlive, KeepAliveTimeout, MaxKeepAliveRequests}。逐个说来: 
KeepAlive是决定开启KeepAlive支持; 
KeepAliveTimeout决定一 个KeepAlive的连接能保持多少时间,Timeout就尽快shutdown链接,若还有数据必须再建立新的连接 了; 
MaxKeepAliveRequests于KeepAliveTimeout相似,意思是服务多少个请求就shutdown连接。 

显然与我们想到的要求不符,再搜索其它配置参数: 

maxConnections 
根据字面意思觉得就应该是这个了。 
去验证吧, 
screenshot! 
最大连接数为10,我们启动30个长连接, 
预期应该是只有10个长连接,实际结果却是远超过10个。这个有点不应该啊。 

实验验证 
原来还有个参数可以觉得连接数的大小 
screenshot 

maxThreads:tomcat起动的最大线程数,即同时处理的任务个数,默认值为200 
acceptCount:当tomcat起动的线程数达到最大时,接受排队的请求个数,默认值为100 

这两个值如何起作用,请看下面三种情况 
情况1:接受一个请求,此时tomcat起动的线程数没有到达maxThreads,tomcat会起动一个线程来处理此请求。 
情况2:接受一个请求,此时tomcat起动的线程数已经到达maxThreads,tomcat会把此请求放入等待队列,等待空闲线程。 
情况3:接受一个请求,此时tomcat起动的线程数已经到达maxThreads,等待队列中的请求个数也达到了acceptCount,此时tomcat会直接拒绝此次请求,返回connection refused 

同时加上maxConnections 
screenshot 

原来tomcat最大连接数取决于maxConnections这个值加上acceptCount这个值,在连接数达到了maxConenctions之后,tomcat仍会保持住连接,但是不处理,等待其它请求处理完毕之后才会处理这个请求。 

源码分析 
tomcat的最大连接数参数是maxConnections,这个值表示最多可以有多少个socket连接到tomcat上。BIO模式下默认最大连接数是它的最大线程数(缺省是200),NIO模式下默认是10000,APR模式则是8192(windows上则是低于或等于maxConnections的1024的倍数)。如果设置为-1则表示不限制。 

在tomcat里通过一个计数器来控制最大连接,比如在Endpoint的Acceptor里大致逻辑如下: 

while (running) { 
    ...    
    //if we have reached max connections, wait 
    countUpOrAwaitConnection(); //计数+1,达到最大值则等待 

    ... 
    // Accept the next incoming connection from the server socket 
    socket = serverSock.accept(); 

    ... 
    processSocket(socket); 

    ... 
    countDownConnection(); //计数-1 
    closeSocket(socket); 

计数器是通过LimitLatch锁来实现的,它内部主要通过一个java.util.concurrent.locks.AbstractQueuedSynchronizer的实现来控制。 

我们将最大连接数设置为10,同时启动超过30个长连接, 
然后通过jstack可以看到acceptor线程阻塞在countUpOrAwaitConnection方法上: 

http-nio-8080-Acceptor-0" daemon prio=10 tid=0x00007f9cfc191000 nid=0x1e07 waiting on condition [0x00007f9ca9fde000] 
   java.lang.Thread.State: WAITING (parking) 
        at sun.misc.Unsafe.park(Native Method) 
        - parking to wait for  <0x000000076595b688> (a org.apache.tomcat.util.threads.LimitLatch$Sync) 
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:156) 
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:969)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1281)
        at org.apache.tomcat.util.threads.LimitLatch.countUpOrAwait(LimitLatch.java:115) 
        at org.apache.tomcat.util.net.AbstractEndpoint.countUpOrAwaitConnection(AbstractEndpoint.java:755) 
        at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:787) 
        at java.lang.Thread.run(Thread.java:662) 
代码层面也解释了这种现象。 

总结 
tomcat能支持最大连接数由maxConnections加上acceptCount来决定。同时maxThreads如何设定? 

以下部分结论引用自:http://duanfei.iteye.com/blog/1894387 
一般的服务器操作都包括两方面:1计算(主要消耗cpu),2等待(io、数据库等) 

第一种极端情况,如果我们的操作是纯粹的计算,那么系统响应时间的主要限制就是cpu的运算能力,此时maxThreads应该尽量设的小,降低同一时间内争抢cpu的线程个数,可以提高计算效率,提高系统的整体处理能力。 

第二种极端情况,如果我们的操作纯粹是IO或者数据库,那么响应时间的主要限制就变为等待外部资源,此时maxThreads应该尽量设的大,这样 才能提高同时处理请求的个数,从而提高系统整体的处理能力。此情况下因为tomcat同时处理的请求量会比较大,所以需要关注一下tomcat的虚拟机内 存设置和linux的open file限制。 

现实应用中,我们的操作都会包含以上两种类型(计算、等待),所以maxThreads的配置并没有一个最优值,一定要根据具体情况来配置。 

最好的做法是:在不断测试的基础上,不断调整、优化,才能得到最合理的配置。 

acceptCount的配置,我一般是设置的跟maxThreads一样大,这个值应该是主要根据应用的访问峰值与平均值来权衡配置的。 

如果设的较小,可以保证接受的请求较快相应,但是超出的请求可能就直接被拒绝 

如果设的较大,可能就会出现大量的请求超时的情况,因为我们系统的处理能力是一定的。