Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1844034
  • 博文数量: 323
  • 博客积分: 5970
  • 博客等级: 大校
  • 技术积分: 2764
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-03 23:13
文章分类

全部博文(323)

文章存档

2018年(2)

2017年(11)

2016年(10)

2015年(27)

2014年(2)

2013年(30)

2012年(197)

2011年(44)

分类: 信息化

2015-06-23 18:49:04

loadrunner_http长连接设置


最近协助同事解决了几个问题,也对loadrunner的一些设置加深了理解,关键是更加知其所以然。

 

1. loadrunner_internet运行时设置 总览:

2. 中文乱码_设置自动字符集转换


3.loadrunner_连接下载超时_tcp是否使用长连接设置

 

帮助文档中的说明:


随后在脚本中进行了不同的设置,进行了结果验证:

3.1 默认值:设置 Keep-Alive HTTP connections ---> Yes
在此设置情况下访问baidu首页,请求头如下图:


3.2 随后,修改 设置 Keep-Alive HTTP connections ---> No
在此设置情况下访问baidu首页,请求头如下图:

3.3通过对比,可以发现:
此设置生效了,而且是通过设置HTTP请求头中的参数实现的,和下述的所说相符。

 

4.至于tcp连接建立连接3次握手,关闭连接4次握手。有兴趣的可以验证下。
  附TCP状态变化图:


下面列一些参考文章,感觉还是蛮有收获的。


HTTP长连接定义:
What is HTTP Persistent Connections?
HTTP persistent connections, also called HTTP keep-alive, or HTTP connection reuse, is the idea of using the same TCP connection to send and receive multiple HTTP requests/responses, as opposed to opening a new one for every single request/response pair. Using persistent connections is very important for improving HTTP performance.

什么是HTTP长连接?
HTTP长连接,与一般每次发起http请求或响应都要建立一个tcp连接不同,http长连接利用同一个tcp连接处理多个http请求和响应,也叫HTTP keep-alive,或者http连接重用。使用http长连接可以提高http请求/响应的性能。


5.HTTP无状态协议和Connection:Keep-Alive容易犯的误区
http://liuzhigong.blog.163.com/blog/static/178272375201141344312315/

名词解释:
HTTP无状态:无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。从另一方面讲,打开一个服务器上的网页和你之前打开这个服务器上的网页之间没有任何联系
如果你要实现一个购物车,需要借助于Cookie或Session或服务器端API(如and)记录这些信息,请求服务器结算页面时同时将这些信息提交到服务器
当你登录到一个网站时,你的登录状态也是由Cookie或Session来“记忆”的,因为服务器并不知道你是否登录
优点:服务器不用为每个客户端连接分配内存来记忆大量状态,也不用在客户端失去连接时去清理内存,以更高效地去处理业务
缺点:客户端的每次请求都需要携带相应参数,服务器需要处理这些参数
参考:,
 
Keep-Alive:参考另外一篇文章HTTP Keep-Alive 详解
 
容易犯的误区:
1、HTTP是一个无状态面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)
2、从HTTP/1.1起,默认都开启了Keep-Alive,保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接
3、Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间

6. http长连接与短连接
http://www.cnblogs.com/Roberts/archive/2010/12/05/1986550.html
可以了解下常见的通信场景:

一、长连接与短连接:

长连接:client方与方先建立连接,连接建立后不断开,然后再进行报文发送和接收。
这种方式下由于通讯连接一直存在。此种方式常用于P2P通信。
短连接:Client方与server每进行一次报文收发交易时才进行通讯连接,交易完毕后立即断开连接。
此方式常用于一点对多点通讯。C/S通信。

二、长连接与短连接的操作过程:

短连接的操作步骤是:
建立连接——数据传输——关闭连接...建立连接——数据传输——关闭连接
长连接的操作步骤是:
建立连接——数据传输...(保持连接)...数据传输——关闭连接

三、长连接与短连接的使用时机:

长连接:短连接多用于操作频繁,点对点的通讯,而且连接数不能太多的情况。
每个TCP连接的建立都需要三次握手,每个TCP连接的断开要四次握手。
如果每次操作都要建立连接然后再操作的话处理速度会降低,所以每次操作
下次操作时直接发送数据就可以了,不用再建立TCP连接。例如:的连接用长连接,
如果用短连接频繁的通信会造成socket错误,频繁的socket创建也是对资源的浪费。
短连接:web网站的http服务一般都用短连接。因为长连接对于服务器来说要耗费一定的资源。
像web网站这么频繁的成千上万甚至上亿客户端的连接用短连接更省一些资源。试想如果都用长连接,
而且同时用成千上万的用户,每个用户都占有一个连接的话,可想而知服务器的压力有多大。
所以并发量大,但是每个用户又不需频繁操作的情况下需要短连接。
总之:长连接和短连接的选择要视需求而定。

四、发送接收方式:

1、异步报文发送和接收是分开的,相互独立,互不影响的。这种方式又分两种情况:
异步双工:接收和发送在同一个程序中,有两个不同的子进程分别负责发送和接送。
异步单工:接送和发送使用两个不同的程序来完成。
2、同步:报文发送和接收是同步进行,即报文发送后等待接送返回报文。同步方式
一般需要考虑超时问题,试想我们发送报文以后也不能无限等待啊,所以我们要设定一个等待
时候。超过等待时间发送方不再等待读返回报文。直接通知超时返回。

五、报文格式:

通信报文格式多样性更多,相应地就必须设计对应的读写报文的接
收和发送报文函数。

阻塞与非阻塞方式

1、非阻塞方式:读函数不停的进行读动作,如果没有报文接收到,等待一段时间后超时返回,
这种情况一般需要指定超时时间。
2、阻塞方式:如果没有接收到报文,则读函数一直处于等待状态,知道报文到达。

循环读写方式

1、一次直接读写报文:在一次接收或发送报文动作中一次性不加分别地全部读取或全部发送报文字节。
2、不指定长度循环读写:这一版发生在短连接进程中,受网络路由等限制,一次较长的报文可能
在网络传输过程中被分解成很多个包,一次读取可能不能全部读完一次报文,这就需要循环读取报文,
知道读完为止。
3、带长度报文头循环读写:这种情况一般在长连接中,由于在长连接中没有条件能够判断循环读写什么时候结束。
必须要加长度报文头。读函数先是读取报文头的长度,再根据这个长度去读报文,实际情况中,报头码制格式还经常不一样,
如果是非ASCII的报文头,还必须转换成ASCII常见的报文头编制有:
1、n个字节的ASCII码。
2、n个字节的BCD码。
3、n个字节的网络整型码。
		

以上是几种比较典型的读写报文方式,可以与通信方式模板一起 预先提供一些典型的API读写函数

当然在实际问题中,可能还必须编写与对方报文格式配套的读写API.在实际情况中,往往需要

把我们自己的系统与别人的系统进行连接, 有了以上模板与API,可以说连接任何方式的通信程序

都不存在问题。

 

7.  http长连接技术文章翻译——关于http长连接有很多重要的概念
http://www.blogjava.net/xjacker/articles/334709.html

尝试翻译片技术文章。

What is HTTP Persistent Connections?
HTTP persistent connections, also called HTTP keep-alive, or HTTP connection reuse, is the idea of using the same TCP connection to send and receive multiple HTTP requests/responses, as opposed to opening a new one for every single request/response pair. Using persistent connections is very important for improving HTTP performance.

什么是HTTP长连接?
HTTP长连接,与一般每次发起http请求或响应都要建立一个tcp连接不同,http长连接利用同一个tcp连接处理多个http请求和响应,也叫HTTP keep-alive,或者http连接重用。使用http长连接可以提高http请求/响应的性能。

There are several advantages of using persistent connections, including:

Network friendly. Less network traffic due to fewer setting up and tearing down of TCP connections.
Reduced latency on subsequent request. Due to avoidance of initial TCP handshake
Long lasting connections allowing TCP sufficient time to determine the congestion state of the network, thus to react appropriately.

使用http长连接有很多好处,包括:

更少的建立和关闭tcp连接,可以减少网络流量。
因为已建立的tcp握手,减少后续请求的延时。
长时间的连接让tcp有充足的时间判断网络的拥塞情况,方便做出下步操作。

The advantages are even more obvious with HTTPS or HTTP over SSL/TLS. There, persistent connections may reduce the number of costly SSL/TLS handshake to establish security associations, in addition to the initial TCP connection set up.
In HTTP/1.1, persistent connections are the default behavior. of any connection. That is, unless otherwise indicated, the client SHOULD assume that the server will maintain a persistent connection, even after error responses from the server. However, the protocol provides means for a client and a server to signal the closing of a TCP connection.

这些优点在使用https连接时更显著。可以减少多次建立高消耗的SSL/TLS握手。
在HTTP/1.1中,默认使用的是长连接方式。客户端默认服务端会保持长连接,即便返回错误响应;除非明确指示不使用长连接。同时,协议中也指定了客户端可以发送关闭信号到服务端来关闭TCP连接。

What makes a connection reusable?
Since TCP by its nature is a stream based protocol, in order to reuse an existing connection, the HTTP protocol has to have a way to indicate the end of the previous response and the beginning of the next one. Thus, it is required that all messages on the connection MUST have a self-defined message length (i.e., one not defined by closure of the connection). Self demarcation is achieved by either setting the Content-Length header, or in the case of chunked transfer encoded entity body, each chunk starts with a size, and the response body ends with a special last chunk.

怎样是连接可以重用?
因为TCP是基于流的协议,所以HTTP协议需要有一种方式来指示前一个响应的结束和后一个响应的开始来重用已建立的连接。所以,它要求连接中传输的信息必须有自定义的消息长度。自定义消息长度可以通过设置 Content-Length 消息头,若传输编码的实体内容块,则每个数据块的标明数据块的大小,而且响应体也是以一个特殊的数据块结束。

What happens if there are proxy servers in between?
Since persistent connections applies to only one transport link, it is important that proxy servers correctly signal persistent/or-non-persistent connections separately with its clients and the origin servers (or to other proxy servers). From a HTTP client or server's perspective, as far as persistence connection is concerned, the presence or absence of proxy servers is transparent.

若中间存在代理服务器将会如何?
因为长连接仅占用一条传输链路,所以代理服务器能否正确得与客户端和服务器端(或者代理服务器)发送长连接或非长连接的信号尤为重要。但是HTTP的客户端或服务器端来看,代理服务器对他们来说是透明的,即便长连接是需要关注的。

What does the current JDK do for Keep-Alive?
The JDK supports both HTTP/1.1 and HTTP/1.0 persistent connections.

When the application finishes reading the response body or when the application calls close() on the InputStream returned by URLConnection.getInputStream(), the JDK's HTTP protocol handler will try to clean up the connection and if successful, put the connection into a connection cache for reuse by future HTTP requests.

The support for HTTP keep-Alive is done transparently. However, it can be controlled by system properties http.keepAlive, and http.maxConnections, as well as by HTTP/1.1 specified request and response headers.

当前的JDK如何处理Keep-Alive?
JDK同时支持HTTP/1.1 和 HTTP/1.0。
当应用程序读取完响应体内容后或者调用 close() 关闭了URLConnection.getInputStream()返回的流,JDK中的HTTP协议句柄将关闭连接,并将连接放到连接缓存中,以便后面的HTTP请求使用。
对HTTP keep-Alive 的支持是透明的。但是,你也可以通过系统属性http.keepAlive和http.maxConnections以及HTTP/1.1协议中的特定的请求响应头来控制。

The system properties that control the behavior. of Keep-Alive are:
http.keepAlive=
default: true

Indicates if keep alive (persistent) connections should be supported.
http.maxConnections=
default: 5

Indicates the maximum number of connections per destination to be kept alive at any given time

HTTP header that influences connection persistence is:
Connection: close

If the "Connection" header is specified with the value "close" in either the request or the response header fields, it indicates that the connection should not be considered 'persistent' after the current request/response is complete.

控制Keep-Alive表现的系统属性有:

http.keepAlive=<布尔值>
默认: true
指定长连接是否支持

http.maxConnections=<整数>
默认: 5
指定对同一个服务器保持的长连接的最大个数。

影响长连接的HTTP header是:
Connection: close
如果请求或响应中的Connection header被指定为close,表示在当前请求或响应完成后将关闭TCP连接。

The current implementation doesn't buffer the response body. Which means that the application has to finish reading the response body or call close() to abandon the rest of the response body, in order for that connection to be reused. Furthermore, current implementation will not try block-reading when cleaning up the connection, meaning if the whole response body is not available, the connection will not be reused.

JDK中的当前实现不支持缓存响应体,所以应用程序必须读取完响应体内容或者调用close()关闭流并丢弃未读内容来重用连接。此外,当前实现在清理连接时并未使用阻塞读,这就意味这如果响应体不可用,连接将不能被重用。

What's new in Tiger?
When the application encounters a HTTP 400 or 500 response, it may ignore the IOException and then may issue another HTTP request. In this case, the underlying TCP connection won't be Kept-Alive because the response body is still there to be consumed, so the socket connection is not cleared, therefore not available for reuse. What the application needs to do is call HttpURLConnection.getErrorStream() after catching the IOException , read the response body, then close the stream. However, some existing applications are not doing this. As a result, they do not benefit from persistent connections. To address this problem, we have introduced a workaround.

The workaround involves buffering the response body if the response is >=400, up to a certain amount and within a time limit, thus freeing up the underlying socket connection for reuse. The rationale behind this is that when the server responds with a >=400 error (client error or server error. One example is "404: File Not Found" error), the server usually sends a small response body to explain whom to contact and what to do to recover.

JDK1.5中的新特性
当应用接收到400或500的HTTP响应时,它将忽略IOException 而另发一个HTTP 请求。这种情况下,底层的TCP连接将不会再保持,因为响应内容还在等待被读取,socket 连接未清理,不能被重用。应用可以在捕获IOException 以后调用HttpURLConnection.getErrorStream() ,读取响应内容然后关闭流。但是现存的应用没有这么做,不能体现出长连接的优势。为了解决这个问题,介绍下workaround。

当响应体的状态码大于或等于400的时候,workaround 将在一定时间内缓存一定数量的响应内容,释放底层的socket连接来重用。基本原理是当响应状态码大于或等于400时,服务器端会发送一个简短的响应体来指明连接谁以及如何恢复连接。

Several new Sun implementation specific properties are introduced to help clean up the connections after error response from the server.

The major one is:

sun.net.http.errorstream.enableBuffering=
default: false

With the above system property set to true (default is false), when the response code is >=400, the HTTP handler will try to buffer the response body. Thus freeing up the underlying socket connection for reuse. Thus, even if the application doesn't call getErrorStream(), read the response body, and then call close(), the underlying socket connection may still be kept-alive and reused.

The following two system properties provide further control to the error stream buffering behavior.:

sun.net.http.errorstream.timeout= in millisecond
default: 300 millisecond

sun.net.http.errorstream.bufferSize= in bytes
default: 4096 bytes

下面介绍一些SUN实现中的特定属性来帮助接收到错误响应体后清理连接:
主要的一个是:
sun.net.http.errorstream.enableBuffering=<布尔值>
默认: false

当上面属性设置为true后,在接收到响应码大于或等于400是,HTTP 句柄将尝试缓存响应内容。释放底层的socket连接来重用。所以,即便应用不调用getErrorStream()来读取响应内容,或者调用 close()关闭流,底层的socket连接也将保持连接状态。

下面的两个系统属性是为了更进一步控制错误流的缓存行为:
sun.net.http.errorstream.timeout= in 毫秒
默认: 300 毫秒

sun.net.http.errorstream.bufferSize= in bytes
默认: 4096 bytes

What can you do to help with Keep-Alive?
Do not abandon a connection by ignoring the response body. Doing so may results in idle TCP connections. That needs to be garbage collected when they are no longer referenced.

If getInputStream() successfully returns, read the entire response body.

When calling getInputStream() from HttpURLConnection, if an IOException occurs, catch the exception and call getErrorStream() to get the response body (if there is any).

Reading the response body cleans up the connection even if you are not interested in the response content itself. But if the response body is long and you are not interested in the rest of it after seeing the beginning, you can close the InputStream. But you need to be aware that more data could be on its way. Thus the connection may not be cleared for reuse.

Here's a code example that complies to the above recommendation:

你如何做可以保持连接为连接状态呢?
不要忽略响应体而丢弃连接。这样会是TCP连接闲置,当不再被引用后将会被垃圾回收器回收。
如果getInputStream()返回成功,读取全部响应内容。如果抛出IOException ,捕获异常并调用getErrorStream() 读取响应内容(如果存在响应内容)。

即便你对响应内容不感兴趣,也要读取它,以便清理连接。但是,如果响应内容很长,你读取到开始部分后就不感兴趣了,可以调用close()来关闭流。值得注意的是,其他部分的数据已在读取中,所以连接将不能被清理进而被重用。

下面是一个基于上面建议的代码样例:

 1try {
 2    URL a = new URL(args[0]);
 3    URLConnection urlc = a.openConnection();
 4    is = conn.getInputStream();
 5    int ret = 0;
 6    while ((ret = is.read(buf)) > 0{
 7      processBuf(buf);
 8    }

 9    // close the inputstream
10    is.close();
11}
 catch (IOException e) {
12    try {
13        respCode = ((HttpURLConnection)conn).getResponseCode();
14        es = ((HttpURLConnection)conn).getErrorStream();
15        int ret = 0;
16        // read the response body
17        while ((ret = es.read(buf)) > 0{
18            processBuf(buf);
19        }

20        // close the errorstream
21        es.close();
22    }
 catch(IOException ex) {
23        // deal with the exception
24    }

25}


If you know ahead of time that you won't be interested in the response body, you should issue a HEAD request instead of a GET request. For example when you are only interested in the meta. info of the web resource or when testing for its validity, accessibility and recent modification. Here's a code snippet:

如果你预先就对响应内容不感兴趣,你可以使用HEAD 请求来代替GET 请求。例如,获取web资源的meta信息或者它的有效性,可访问性以及最近的修改。下面是代码片段:

1URL a = new URL(args[0]);
2URLConnection urlc = a.openConnection();
3HttpURLConnection httpc = (HttpURLConnection)urlc;
4// only interested in the length of the resource
5httpc.setRequestMethod("HEAD");
6int len = httpc.getContentLength();

 


根据前面的图可以知道,Keep Alive 属性有服务端和客户端两头都可以设置,
那么服务器端如何设置才可以获得更好的性能呢?

8.Apache 中 Keep Alive 配置的合理使用——里面的公式和计算方法,没看懂,不要迷信还是要实证
http://blog.163.com/hai_zone/blog/static/264611372010718103838356/?fromdm&fromSearch&isFromSearchEngine=yes

在 Apache 服务器中,KeepAlive 是一个布尔值,On 代表打开,Off 代表关闭,这个指令在其他众多的 HTTPD 服务器中都是存在的。

  KeepAlive 配置指令决定当处理完用户发起的 HTTP 请求后是否立即关闭 TCP 连接,如果 KeepAlive 设置为On,那么用户完成一次访问后,不会立即断开连接,如果还有请求,那么会继续在这一次 TCP 连接中完成,而不用重复建立新的 TCP 连接和关闭TCP 连接,可以提高用户访问速度。

  那么我们考虑3种情况:
  1。用户浏览一个网页时,除了网页本身外,还引用了多个 javascript. 文件,多个 css 文件,多个图片文件,并且这些文件都在同一个 HTTP 服务器上。
  2。用户浏览一个网页时,除了网页本身外,还引用一个 javascript. 文件,一个图片文件。
  3。用户浏览的是一个动态网页,由程序即时生成内容,并且不引用其他内容。

  对于上面3中情况,我认为:1 最适合打开 KeepAlive ,2 随意,3 最适合关闭 KeepAlive

  下面我来分析一下原因。

  在 Apache 中,打开和关闭 KeepAlive 功能,服务器端会有什么异同呢?

  先看看理论分析。

  打开 KeepAlive 后,意味着每次用户完成全部访问后,都要保持一定时间后才关闭会关闭 TCP 连接,那么在关闭连接之前,必然会有一个Apache 进程对应于该用户而不能处理其他用户,假设 KeepAlive 的超时时间为 10 秒种,服务器每秒处理 50个独立用户访问,那么系统中 Apache 的总进程数就是 10 * 50 = 500 个,如果一个进程占用 4M 内存,那么总共会消耗 2G内存,所以可以看出,在这种配置中,相当消耗内存,但好处是系统只处理了 50次 TCP 的握手和关闭操作。

  如果关闭 KeepAlive,如果还是每秒50个用户访问,如果用户每次连续的请求数为3个,那么 Apache 的总进程数就是 50 * 3= 150 个,如果还是每个进程占用 4M 内存,那么总的内存消耗为 600M,这种配置能节省大量内存,但是,系统处理了 150 次 TCP的握手和关闭的操作,因此又会多消耗一些 CPU 资源。

  在看看实践的观察。

  我在一组大量处理动态网页内容的服务器中,起初打开 KeepAlive功能,经常观察到用户访问量大时Apache进程数也非常多,系统频繁使用交换内存,系统不稳定,有时负载会出现较大波动。关闭了 KeepAlive功能后,看到明显的变化是: Apache 的进程数减少了,空闲内存增加了,用于文件系统Cache的内存也增加了,CPU的开销增加了,但是服务更稳定了,系统负载也比较稳定,很少有负载大范围波动的情况,负载有一定程度的降低;变化不明显的是:访问量较少的时候,系统平均负载没有明显变化。


  总结一下:
  在内存非常充足的服务器上,不管是否关闭 KeepAlive 功能,服务器性能不会有明显变化;
  如果服务器内存较少,或者服务器有非常大量的文件系统访问时,或者主要处理动态网页服务,关闭 KeepAlive 后可以节省很多内存,而节省出来的内存用于文件系统Cache,可以提高文件系统访问的性能,并且系统会更加稳定。


  补充1:
  关于是否应该关闭 KeepAlive 选项,我觉得可以基于下面的一个公式来判断。

  在理想的网络连接状况下,系统的 Apache 进程数和内存使用可以用如下公式表达:
HttpdProcessNumber = KeepAliveTimeout * TotalRequestPerSecond / Average(KeepAliveRequests)
HttpdUsedMemory = HttpdProcessNumber * MemoryPerHttpdProcess

  换成中文:
总Apache进程数 = KeepAliveTimeout * 每秒种HTTP请求数 / 平均KeepAlive请求
Apache占用内存 = 总Apache进程数 * 平均每进程占用内存数

  需要特别说明的是:
  [平均KeepAlive请求] 数,是指每个用户连接上服务器后,持续发出的 HTTP 请求数。当 KeepAliveTimeout 等 0或者 KeepAlive 关闭时,KeepAliveTimeout 不参与乘的运算从上面的公式看,如果 [每秒用户请求]多,[KeepAliveTimeout] 的值大,[平均KeepAlive请求] 的值小,都会造成 [Apache进程数] 多和 [内存]多,但是当 [平均KeepAlive请求] 的值越大时,[Apache进程数] 和 [内存] 都是趋向于减少的。

  基于上面的公式,我们就可以推算出当 平均KeepAlive请求 <= KeepAliveTimeout 时,关闭 KeepAlive 选项是划算的,否则就可以考虑打开。

     补充2: KeepAlive 该参数控制Apache是否允许在一个连接中有多个请求,默认打开。但对于大多数论坛类型站点来说,通常设置为off以关闭该支持。

     补充3: 如果服务器前跑有应用squid服务,或者七层设备,KeepAlive On 设定要开启持续长连接

实际在 前端有 squid 的情况下, KeepAlive 很关键。记得 On

 


9.不可忽略的KeepAlive —— Apache 中 Keep Alive 配置
http://tomyz0223.iteye.com/blog/603187

在网页开发过程中,Keep-Alive是HTTP协议中非常重要的一个属性。大家知道HTTP构建在TCP之上。在HTTP早期实现中,每个HTTP请求都要打开一个socket连接。这种做效率很低,因为一个Web 页面中的很多HTTP请求都指向同一个服务器。例如,很多为Web页面中的图片发起的请求都指向一个通用的图片服务器。持久连接的引入解决了多对已请求服务器导致的socket连接低效性的问题。它使浏览器可以再一个单独的连接上进行多个请求。浏览器和服务器使用Connection头ilai指出对 Keep-Alive的支持。

 

笔者在去年遇到一个跟Keep-Alive的问题:

 

问题现象:一个JSP页面,居然要耗时40多秒。网页中有大量的图片的CSS

 

问题解决:原因也找了半天,原来Apache配置里面,把Keep-Alive的开关关闭了。这个是个大问题,工程师为什么要关闭它,原来他考虑的太简单了,我们知道Apache适合处于短连接的请求,处理时间越短,并发数才能上去,原来他是这么考虑,但是没有办法,只能这样了,还是打开Keep-Alive开关吧。

 

当然,不是所有的情况都设置KeepAlive为On,下面的文字总结比较好:

 

【在使用的过程中,属性我一直保持为默认值On,其实,该属性设置为On还是Off还是要具体问题具体分析的,在生产环境中的影响还是蛮大的。

选项到底有什么用处?如果你用过,应该知道Mysql的连接属性中有一个与KeepAlive类似的Persistent Connection,即:长连接(PConnect)。该属性打开的话,可以使一次TCP连接为同一用户的多次请求服务,提高了响应速度。

比如很多网页中图片、CSS、JS、Html都在一台Server上,当用户访问其中的Html网页时,网页中的图片、Css、Js都构成了访问请求,打开KeepAlive属性可以有效地降低TCP握手的次数(当然浏览器对同一域下同时请求的图片数有限制,一般是2),减少httpd进程数,从而降低内存的使用(假定prefork模式)。和两个属性在KeepAlive=On时起作用,可以控制持久连接的生存时间和最大服务请求数。

不过,上面说的只是一种情形,那就是静态网页居多的情况下,并且网页中的其他请求与网页在同一台Server上。当你的应用动态程序(比如:)居多,用户访问时由动态程序即时生成html内容,html内容中图片素材和Css、Js等比较少或者散列在其他Server上时,KeepAlive=On反而会降低Apache的性能。为什么呢?

前面提到过,KeepAlive=On时,每次用户访问,打开一个TCP连接,Apache都会保持该连接一段时间,以便该连接能连续为同一client服务,在KeepAliveTimeOut还没到期并且MaxKeepAliveRequests还没到阈值之前,Apache必然要有一个httpd进程来维持该连接,httpd进程不是廉价的,他要消耗内存和CPU时间片的。假如当前Apache每秒响应100个用户访问,KeepAliveTimeOut=5,此时httpd进程数就是100*5=500个(模式),一个httpd进程消耗5M内存的话,就是500*5M=2500M=2.5G,夸张吧?当然,Apache与Client只进行了100次TCP连接。如果你的内存够大,系统负载不会太高,如果你的内存小于2.5G,就会用到Swap,频繁的Swap切换会加重CPU的Load。

现在我们关掉KeepAliveApache仍然每秒响应100个用户访问,因为我们将图片、js、css等分离出去了,每次访问只有1个request,此时httpd的进程数是100*1=100个,使用内存100*5M=500M,此时Apache与Client也是进行了100次TCP连接。性能却提升了太多。

总结:

1、当你的Server内存充足时,KeepAlive=On还是Off对系统性能影响不大。

2、当你的Server上静态网页(Html、图片、Css、Js)居多时,建议打开KeepAlive

3、当你的Server多为动态请求(因为连接数据库,对文件系统访问较多),KeepAlive关掉,会节省一定的内存,节省的内存正好可以作为文件系统的Cache(vmstat命令中cache一列),降低I/O压力。

PS:当KeepAlive=On时,KeepAliveTimeOut的设置其实也是一个问题,设置的过短,会导致Apache频繁建立连接,给Cpu造成压力,设置的过长,系统中就会堆积无用的Http连接,消耗掉大量内存,具体设置多少,可以进行不断的调节,因你的网站浏览和服务器配置而异。

 


10. HTTP协议中的持久连接connection:keep-alive,的一些问题和思考,参考。

关于keep-alive这个东西,是否要开放,对性能究竟有何影响,目前大家估计也都是从经验方面来设置的,没有从理论层面的讨论,今天我来挖个坑,希望大家踊跃往里跳。

简单整理一下问题要点:

1,keep-alive的原理是什么,能解决什么问题?
2,web server设置了keep-alive,是否需要下级协议盏的支持才起作用?例如是否要启用tcp/ip的keep alive机制?
3,web server设置了keep-alive,是否要客户端浏览器有相应支持?是否要客户端协议盏的支持?如果要得话,我们通常使用的各种系统以及各种浏览器支持的情况怎样?
4,keep-alive会带来性能提升吗?具体体现在什么方面?例如可承载高并发访问?或者是可提升传输性能?再或者可减轻服务器压力?在低访问量和高访问量情况下有何区别?


就我个人的理解来看,keep-alive是利用了tcp的双向全双工连接特性,在web-server端可以不断开连接,来接受客户端更多的请求,应该是能够改善连接时间,不过似乎在连接非常多的情况下会大大加重服务器负担,需要tcp/ip协议盏支持,并且不同客户端之间有不同的设定,具体细节还不详。
楼上的文章受教了,简单说就是从http协议的情况来看,默认1.0是关闭的,需要在http头加入Connection: Keep-Alive才能发起keep-alive的连接,而http1.1协议默认启用keep-alive,如果加入Connection: close 则就强制关闭。

目前大部分浏览器都是用http1.1协议,也就是说默认都会发起keep-alive的连接请求了,所以是否能完成一个完整的keep-alive连接就看服务器设置情况。

我推测服务器返回的http头应该包含关于keep-alive的信息,回去抓包正是一下。


楼上的文章说我在网上找到的,事实上服务器确实会返回关于keep-alive的消息。最简单的方法,不需要任何额外的软件,你可以打开迅雷,随便下载一个文件,然后查看任务详情里面,他就有http请求和回应的header信息,从这个里面可以清楚的看到客户端在header设置了keep- alive,而服务器返回时也有这个header字段。
不过我刚开始还在担心一个问题,他是怎么保持连接的呢?既然说到http是无状态的,那server根本就不知道这个连接建立多久了,如果数据已经传送完毕,那客户端应该不会继续想server请求了吧?既然没有数据交互,也没有状态信息,那怎么保持甚至是结束这个连接呢?至少我在网上看到的答案是这个连接是不能保持很久的,一般最多空闲两分钟而已。这么来看还是可以接受的。


另外一个问题是,网上关于这方面的资料好像很少,至少中文的是这样,百度googlge不到。但是实际上《计算机网络--自顶向下方法与internet 特色》这本书是讲得很清楚的。在中译本P60或原版P89就有十分详细生动的解释,这里没有时间把他写上来了。当然,书中的一个不足是没有在那里提到这个持久连接是在header中设置connection字段来实现的,当然了,这也是因为那个时候书上还没有讲到http header的结构。


11. FireFox下的HTTP请求构造调试工具Tamper 
Tamper是firefox下的HTTP请求监听和调试工具,功能和Fiddler差不多,但用起来比Fiddler更加方便,毕竟是firefox下的扩展。同样的,
可以对请求进行拦截,修改请求头和请求参数等信息,方便进行程序调试和问题监控。可以从这里下载:
直接在"附加插件"里搜索Tamper吧:

 


参考文章汇总:

1.HTTP无状态协议和Connection:Keep-Alive容易犯的误区
http://liuzhigong.blog.163.com/blog/static/178272375201141344312315/

2. http长连接与短连接——可以了解下常见的通信场景
http://www.cnblogs.com/Roberts/archive/2010/12/05/1986550.html

3.  http长连接技术文章翻译——关于http长连接有很多重要的概念
http://www.blogjava.net/xjacker/articles/334709.html

4.Apache 中 Keep Alive 配置的合理使用——里面的公式和计算方法,没看懂,不要迷信还是要实证
http://blog.163.com/hai_zone/blog/static/264611372010718103838356/?fromdm&fromSearch&isFromSearchEngine=yes

5.不可忽略的KeepAlive —— Apache 中 Keep Alive 配置
http://tomyz0223.iteye.com/blog/603187

6.HTTP协议中的持久连接connection:keep-alive,的一些问题和思考,参考。

 

阅读(1930) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~