<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>OurApache &#187; KeepAlive</title>
	<atom:link href="http://ourapache.com/archives/tag/keepalive/feed" rel="self" type="application/rss+xml" />
	<link>http://ourapache.com</link>
	<description>我们致力于一个Apache知识的分享网站</description>
	<lastBuildDate>Tue, 13 Apr 2010 05:18:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>关于HTTP 协议中的 KeepAlive</title>
		<link>http://ourapache.com/archives/236</link>
		<comments>http://ourapache.com/archives/236#comments</comments>
		<pubDate>Wed, 01 Apr 2009 11:27:11 +0000</pubDate>
		<dc:creator>OurApache</dc:creator>
				<category><![CDATA[Apache高级应用]]></category>
		<category><![CDATA[KeepAlive]]></category>

		<guid isPermaLink="false">http://www.ourapache.com/?p=236</guid>
		<description><![CDATA[其中使用PHP实现持久的HTTP连接，让我费了很多心思。
曾经想过使用C语言编写一个PHP的扩展来实现，后来发现pfsockopen这个函数，让我豁然开朗，避免重新发明一个轮子，呵呵。]]></description>
			<content:encoded><![CDATA[<p>这篇文章已经写完将近一年了，最近从历史邮件里面翻出来，和大家分享一下。<br />
其中使用PHP实现持久的HTTP连接，让我费了很多心思。<br />
曾经想过使用C语言编写一个PHP的扩展来实现，后来发现pfsockopen这个函数，让我豁然开朗，避免重新发明一个轮子，呵呵。</p>
<p>一，KeepAlive的概念：</p>
<p>参见 http://en.wikipedia.org/wiki/HTTP_persistent_connection</p>
<p>二，KeepAlive的客户端实现：</p>
<p>使用了PHP支持的 pfsockopen 来实现，参见：http://cn.php.net/pfsockopen</p>
<p>KeepAlive必要的Header有：</p>
<blockquote><p>Connection: Keep-Alive<br />
Content-Length: xxx</p></blockquote>
<p>三，性能对比测试：</p>
<p>几种对比实现方式：</p>
<blockquote><p>1，使用fsockopen来实现，读取body内容后，关闭连接，参见测试程序中的ohttp_get实现。<br />
2，使用pfsockopen来实现，读取body内容后，不关闭连接，参见测试程序中的phttp_get实现。<br />
3，php实现的file_get_contents<br />
4，第三方测试工具ab</p></blockquote>
<p>前三种测试在测试程序中都包含了。</p>
<p>测试用例 一：</p>
<p>前三种php实现的客户端单进程单线程请求lighttpd服务器一个16字节的静态文件。顺序请求10000次。<br />
客户端与服务器部署在不同服务器，通过内网请求。</p>
<p>测试结果：</p>
<p>第一次：</p>
<blockquote><p>[root@localhost ~]# /opt/bin/php tp.php<br />
phttp_get: 5.3641529083252<br />
ohttp_get: 8.1628580093384<br />
file_get_contents: 12.217950105667</p></blockquote>
<p>第二次：</p>
<blockquote><p>[root@localhost ~]# /opt/bin/php tp.php<br />
phttp_get: 5.033059835434<br />
ohttp_get: 9.589075088501<br />
file_get_contents: 12.775387048721</p></blockquote>
<p>第三次：</p>
<blockquote><p>[root@localhost ~]# /opt/bin/php tp.php<br />
phttp_get: 5.0181269645691<br />
ohttp_get: 8.2286441326141<br />
file_get_contents: 11.089616060257</p></blockquote>
<p>测试用例 二：</p>
<p>使用第三方工具ab来进行测试，-k参数开打开keepalive支持，不做并发测试，顺序请求10000次。<br />
客户端与服务器部署在不同服务器，通过内网请求。</p>
<p>以下测试结果部分省略：</p>
<p>未打开keepalive：</p>
<blockquote><p>[root@localhost ~]# ab -n 10000 -c 1 “http://10.69.2.206:8080/sms/ns2/save_msg.txt”</p>
<p>Finished 10000 requests</p>
<p>Concurrency Level: 1<br />
Time taken for tests: 10.410467 seconds<br />
Complete requests: 10000<br />
Failed requests: 0<br />
Write errors: 0<br />
Total transferred: 2480000 bytes<br />
HTML transferred: 160000 bytes<br />
Requests per second: 960.57 [#/sec] (mean)<br />
Time per request: 1.041 [ms] (mean)<br />
Time per request: 1.041 [ms] (mean, across all concurrent requests)<br />
Transfer rate: 232.55 [Kbytes/sec] received</p>
<p>Connection Times (ms)<br />
min mean[+/-sd] median max<br />
Connect: 0 0 30.0 0 3002<br />
Processing: 0 0 0.4 0 9<br />
Waiting: 0 0 0.3 0 9<br />
Total: 0 0 30.0 0 3003</p></blockquote>
<p>打开keepalive：</p>
<blockquote><p>[root@localhost ~]# ab -k -n 10000 -c 1 “http://10.69.2.206:8080/sms/ns2/save_msg.txt”</p>
<p>Finished 10000 requests</p>
<p>Concurrency Level: 1<br />
Time taken for tests: 4.148619 seconds<br />
Complete requests: 10000<br />
Failed requests: 0<br />
Write errors: 0<br />
Keep-Alive requests: 9412<br />
Total transferred: 2527060 bytes<br />
HTML transferred: 160000 bytes<br />
Requests per second: 2410.44 [#/sec] (mean)<br />
Time per request: 0.415 [ms] (mean)<br />
Time per request: 0.415 [ms] (mean, across all concurrent requests)<br />
Transfer rate: 594.66 [Kbytes/sec] received</p>
<p>Connection Times (ms)<br />
min mean[+/-sd] median max<br />
Connect: 0 0 0.1 0 5<br />
Processing: 0 0 2.1 0 203<br />
Waiting: 0 0 2.1 0 203<br />
Total: 0 0 2.1 0 203</p></blockquote>
<p>四，在实际中的应用</p>
<p>以上实现的phttp_get和mysql memcache的 中的“保持连接”概念类似，这种技术一般来说，只适用于fastcgi模式的web服务器。<br />
对于本机之间的http通信，在测试过程中发现phttp_get的优势有限，基本合乎逻辑。<br />
对于本身处理时间比较长的服务，phttp_get的优势也不明显。<br />
综上，phttp_get适用于fastcgi模式的web应用调用远程http服务，且此http服务器响应时间比较短的情况。</p>
<p>五，服务端需要注意的事项</p>
<p>1，http服务器必须支持HTTP/1.1协议<br />
2，php应用必须返回Content-Length:的header，具体实现参见：</p>
<p>http://cn.php.net/manual/en/function.ob-get-length.php</p>
<p>需要在代码中加入：</p>
<blockquote><p>ob_start();<br />
$size=ob_get_length();<br />
header(”Content-Length: $size”);<br />
ob_end_flush();</p></blockquote>
<p>最后附上测试代码：</p>
<blockquote><p>&lt;?php</p>
<p>//$url=http://10.69.2.206:8080/sms/ns2/save_msg.txt</p>
<p>function ohttp_get($host,$port,$query,&amp;$body)<br />
{<br />
$fp=pfsockopen($host,$port,$errno,$errstr,1);<br />
if(!$fp)<br />
{<br />
var_dump($errno,$errstr);<br />
return -1;<br />
}<br />
$out = “GET ${query} HTTP/1.1\r\n”;<br />
$out.= “Host: ${host}\r\n”;<br />
$out.= “Connection: close\r\n”;<br />
$out.= “\r\n”;<br />
fwrite($fp,$out);<br />
$line=trim(fgets($fp));<br />
$header.=$line;<br />
list($proto,$rcode,$result)=explode(” “,$line);<br />
$len=-1;<br />
while( ($line=trim(fgets($fp))) != “” )<br />
{<br />
$header.=$line;<br />
if(strstr($line,”Content-Length:”))<br />
{<br />
list($cl,$len)=explode(” “,$line);<br />
}<br />
if(strstr($line,”Connection: close”))<br />
{<br />
$close=true;<br />
}<br />
}<br />
if($len &lt; 0)<br />
{<br />
echo “ohttp_get must cope with Content-Length header!\n”;<br />
return -1;<br />
}<br />
$body=fread($fp,$len);<br />
if($close)<br />
fclose($fp);<br />
return $rcode;<br />
}<br />
function phttp_get($host,$port,$query,&amp;$body)<br />
{<br />
$fp=pfsockopen($host,$port,$errno,$errstr,1);<br />
if(!$fp)<br />
{<br />
var_dump($errno,$errstr);<br />
return -1;<br />
}<br />
$out = “GET ${query} HTTP/1.1\r\n”;<br />
$out.= “Host: ${host}\r\n”;<br />
$out.= “Connection: Keep-Alive\r\n”;<br />
$out.= “\r\n”;<br />
fwrite($fp,$out);<br />
$line=trim(fgets($fp));<br />
$header.=$line;<br />
list($proto,$rcode,$result)=explode(” “,$line);<br />
$len=-1;<br />
while( ($line=trim(fgets($fp))) != “” )<br />
{<br />
$header.=$line;<br />
if(strstr($line,”Content-Length:”))<br />
{<br />
list($cl,$len)=explode(” “,$line);<br />
}<br />
if(strstr($line,”Connection: close”))<br />
{<br />
$close=true;<br />
}<br />
}<br />
if($len &lt; 0)<br />
{<br />
echo “phttp_get must cope with Content-Length header!\n”;<br />
return -1;<br />
}<br />
$body=fread($fp,$len);<br />
if($close)<br />
fclose($fp);<br />
return $rcode;<br />
}</p>
<p>$time1=microtime(true);<br />
for($i=0;$i&lt;10000;$i++)<br />
{<br />
$host=”10.69.2.206″;<br />
$port=8080;<br />
$query=”/sms/ns2/save_msg.txt”;<br />
$body=””;<br />
$r=ohttp_get($host,$port,$query,$body);<br />
if($r != 200)<br />
{<br />
echo “return code : $r\n”;<br />
}<br />
}<br />
$time2=microtime(true);<br />
for($i=0;$i&lt;10000;$i++)<br />
{<br />
$url=”http://10.69.2.206:8080/sms/ns2/save_msg.txt”;<br />
$host=”10.69.2.206″;<br />
$port=8080;<br />
$query=”/sms/ns2/save_msg.txt”;<br />
$body=””;<br />
$r=phttp_get($host,$port,$query,$body);<br />
if($r != 200)<br />
{<br />
echo “return code : $r\n”;<br />
}<br />
}<br />
$time3=microtime(true);<br />
for($i=0;$i array( ‘timeout’ =&gt; 1 )<br />
)<br />
);<br />
$body=file_get_contents($url, 0, $ctx);<br />
$r=200;<br />
if($r != 200)<br />
{<br />
echo “return code : $r\n”;<br />
}<br />
}<br />
$time4=microtime(true);</p>
<p>echo “phttp_get: “.($time3-$time2).”\n”;<br />
echo “ohttp_get: “.($time2-$time1).”\n”;<br />
echo “file_get_contents: “.($time4-$time3).”\n”;</p>
<p>?&gt;</p></blockquote>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2009年02月10号 -- <a href="http://ourapache.com/archives/109" title="谈谈Apache的优化">谈谈Apache的优化</a></li><li>2009年01月6号 -- <a href="http://ourapache.com/archives/29" title="Apache 中KeepAlive 配置的合理使用(优化) ">Apache 中KeepAlive 配置的合理使用(优化) </a></li><li>2009年01月5号 -- <a href="http://ourapache.com/archives/21" title="关于keepalive的解释">关于keepalive的解释</a></li></ul>
	标签：<a href="http://ourapache.com/archives/category/advanced" title="Apache高级应用" rel="tag">Apache高级应用</a>, <a href="http://ourapache.com/archives/tag/keepalive" title="KeepAlive" rel="tag">KeepAlive</a><br />
]]></content:encoded>
			<wfw:commentRss>http://ourapache.com/archives/236/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>谈谈Apache的优化</title>
		<link>http://ourapache.com/archives/109</link>
		<comments>http://ourapache.com/archives/109#comments</comments>
		<pubDate>Tue, 10 Feb 2009 06:52:58 +0000</pubDate>
		<dc:creator>OurApache</dc:creator>
				<category><![CDATA[Apache高级应用]]></category>
		<category><![CDATA[KeepAlive]]></category>
		<category><![CDATA[优化]]></category>

		<guid isPermaLink="false">http://www.ourapache.com/?p=109</guid>
		<description><![CDATA[今天说说Apache的优化。为什么要优化？因为服务器资源不够用。资源有很多方面，但根据木桶理论，只要有一种资源不够用，整个服务器的性能就会受到影响（所谓瓶颈）。]]></description>
			<content:encoded><![CDATA[<p>今天说说Apache的优化。为什么要优化？因为服务器资源不够用。资源有很多方面，但根据木桶理论，只要有一种资源不够用，整个服务器的性能就会受到影响（所谓瓶颈）。</p>
<p><strong>服务器资源</strong></p>
<p>那么服务器的资源包括哪些？对于网站来说主要是<strong>CPU</strong>、<strong>TCP连接数</strong>这两者。 CPU表现在任务数上，在Linux下使用<strong>平均负载</strong>(loadavg)来衡量。可通过以下命令来查看（参考<a href="http://tech.idv2.com/2006/08/31/about-proc-loadavg/"><span style="color: #448608;">这篇文章</span></a>）：</p>
<p>cat /proc/loadavg</p>
<p>对于单CPU的服务器，loadavg高于1，表明任务队列出现了等待，CPU忙不过来了。超过2以上就会明显感到性能降低了。</p>
<p>TCP连接数可通过以下命令查看：<br />
netstat -ant | grep :80 | wc -l</p>
<p>如果要实时监控服务器资源，可参考<a href="http://www.opennms.org/"><span style="color: #448608;">OpenNMS</span></a>项目。</p>
<p><span style="color: blue;">注1：内存不算，低廉的价格使得网站服务器很少有因为内存不够而down掉的。</span><br />
<span style="color: blue;">注2：CPU%是瞬时的CPU使用率，通常无法反映出整体负载。</span></p>
<p> </p>
<p><strong>Apache配置命令</strong></p>
<p>Apache在资源方面的配置命令主要有以下几条。</p>
<div>
<table border="0">
<tbody>
<tr>
<td><a href="http://ourapache.com/archives/tag/keepalive" class="st_tag internal_tag" rel="tag" title="标签 KeepAlive 下的日志">KeepAlive</a></td>
<td>是否允许持续连接</td>
</tr>
<tr>
<td>MaxKeepAliveRequests</td>
<td>允许的持续连接的最大数</td>
</tr>
<tr>
<td>KeepAliveTimeout</td>
<td>持续连接在没有请求多少秒后切断</td>
</tr>
<tr>
<td>StartServers</td>
<td>最初启动时启动多少个服务器进程</td>
</tr>
<tr>
<td>MinSpareServers</td>
<td>空闲服务器进程的最小数</td>
</tr>
<tr>
<td>MaxSpareServers</td>
<td>空闲服务器进程的最大数</td>
</tr>
<tr>
<td>MaxRequestsPerChild</td>
<td>每个子进程处理的最大请求数</td>
</tr>
</tbody>
</table>
</div>
<p><strong>KeepAlive</strong></p>
<p>前三个KeepAlive相关的指令用来设置持续连接。通常都是每个HTTP请求对应一个TCP连接，但对于一个包含许多图片的网页来说，客户端会在瞬间发出多个HTTP请求，此时多次建立TCP连接会大大降低响应速度。此时通过持续连接，可以允许用户在一个TCP连接中发出多个HTTP请求，减少TCP连接建立次数，提高响应速度。</p>
<p>这种情况下，应当通过access_log统计出连续HTTP请求出现的次数、间隔时间、访问量，以确定 MaxKeepAliveRequests 和 KeepAliveTimeout 的值。 KeepAliveTimeout 太小发挥不了持续连接的作用；太大了，持续连接迟迟不断，浪费TCP连接数不说，更糟糕的是系统中的 httpd 进程数目会因此不断增加，使得系统负载升高，甚至会导致服务器失去响应。</p>
<p>但是在处理动态网页请求时，由于用户很少会瞬间请求多个动态网页（一般都是打开页面之后阅读好半天才点下一页），此时打开KeepAlive无异于浪费TCP连接数。</p>
<p>结论就是，放动态网页的就 KeepAlive Off 以提高吞吐量，放静态内容如图片、js代码等就 KeepAlive On 以减少TCP连接建立次数。</p>
<p>但一个Apache只能有一种 KeepAlive 设置，怎么办？很简单，弄两台服务器，一个专门放脚本，一个专门放图片。</p>
<p><strong>服务器进程数</strong></p>
<p>再说说下面的 StartServers、MinSpareServers、MaxSpareServers。 StartServers基本不用修改，因为Apache会自动调节子进程数。 MinSpareServers和MaxSpareServers是空闲子进程数目，何为空闲子进程？假设某一时刻系统中共有30个httpd进程，其中一个是父进程，20个在处理请求，那么空闲子进程数就是9个。</p>
<p>空闲进程少了，大量的突发请求会使服务器疲于进程创建，降低效率；而太多反而会增加系统进程数，增大系统负载。</p>
<p>实际上，默认值已足够处理一般的突发请求，所以除非是流量特别特别巨大的网站，否则不要修改这些设置。</p>
<p><span style="color: blue;">就算流量特别特别大，也是通过负载平衡系统来降低每台服务器的访问量，不会修改这几个值。</span></p>
<p><strong>MaxRequestsPerChild</strong></p>
<p>这个值设置子进程在处理多少个请求之后自动结束。这个选项是用来防止进程由于内存泄漏等使用内存过多。一般默认值即可。</p>
<p><strong>总结</strong></p>
<p>说来说去其实最重要的还是 KeepAlive 的设置，而性能调节也就是调整 KeepAlive、KeepAliveTimeout 值。</p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2009年04月1号 -- <a href="http://ourapache.com/archives/236" title="关于HTTP 协议中的 KeepAlive">关于HTTP 协议中的 KeepAlive</a></li><li>2009年01月6号 -- <a href="http://ourapache.com/archives/29" title="Apache 中KeepAlive 配置的合理使用(优化) ">Apache 中KeepAlive 配置的合理使用(优化) </a></li><li>2009年01月5号 -- <a href="http://ourapache.com/archives/21" title="关于keepalive的解释">关于keepalive的解释</a></li><li>2008年12月27号 -- <a href="http://ourapache.com/archives/3" title="apache的配置优化">apache的配置优化</a></li></ul>
	标签：<a href="http://ourapache.com/archives/category/advanced" title="Apache高级应用" rel="tag">Apache高级应用</a>, <a href="http://ourapache.com/archives/tag/keepalive" title="KeepAlive" rel="tag">KeepAlive</a>, <a href="http://ourapache.com/archives/tag/%e4%bc%98%e5%8c%96" title="优化" rel="tag">优化</a><br />
]]></content:encoded>
			<wfw:commentRss>http://ourapache.com/archives/109/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache 中KeepAlive 配置的合理使用(优化)</title>
		<link>http://ourapache.com/archives/29</link>
		<comments>http://ourapache.com/archives/29#comments</comments>
		<pubDate>Tue, 06 Jan 2009 06:11:34 +0000</pubDate>
		<dc:creator>OurApache</dc:creator>
				<category><![CDATA[Apache基础知识]]></category>
		<category><![CDATA[KeepAlive]]></category>

		<guid isPermaLink="false">http://www.ourapache.com/?p=29</guid>
		<description><![CDATA[我的这个网站架设在美国的VPS上,有1G的内存.但是今天发现服务器的内存被完全用光了,非常的惊险,连SSH链接都几乎无法建立.肯定是Apache吃光了我的内存,于是赶紧优化,内存占用大幅降低.一切终于流畅起来了.下面把我参考过的文章顺过来,给朋友们分享]]></description>
			<content:encoded><![CDATA[<p>在 <strong>Apache</strong> <strong>服务器</strong>中，<strong><a href="http://ourapache.com/archives/tag/keepalive" class="st_tag internal_tag" rel="tag" title="标签 KeepAlive 下的日志">KeepAlive</a></strong> 是一个布尔值，On 代表打开，Off 代表关闭，这个指令在其他众多的 HTTPD 服务器中都是存在的。</p>
<p>KeepAlive 配置指令决定当处理完用户发起的 HTTP 请求后是否立即关闭 TCP 连接，如果 KeepAlive 设置为 On，那么用户完成一次访问后，不会立即断开连接，如果还有请求，那么会继续在这一次 TCP 连接中完成，而不用重复建立新的 TCP 连接和关闭 TCP 连接，可以提高用户访问速度。</p>
<p>那么我们考虑3种情况：</p>
<p>1。用户浏览一个网页时，除了网页本身外，还引用了多个 javascript. 文件，多个 css 文件，多个图片文件，并且这些文件都在同一个 HTTP 服务器上。<br />
2。用户浏览一个网页时，除了网页本身外，还引用一个 javascript. 文件，一个图片文件。<br />
3。用户浏览的是一个动态网页，由程序即时生成内容，并且不引用其他内容。</p>
<p>对于上面3中情况，我认为：1 最适合打开 KeepAlive ，2 随意，3 最适合关闭 KeepAlive</p>
<p>下面我来分析一下原因。</p>
<p>在 Apache 中，打开和关闭 KeepAlive 功能，服务器端会有什么异同呢？</p>
<p>先看看理论分析。</p>
<p>打开 KeepAlive 后，意味着每次用户完成全部访问后，都要保持一定时间后才关闭会关闭 TCP 连接，那么在关闭连接之前，必然会有一个 Apache 进程对应于该用户而不能处理其他用户，假设 KeepAlive 的超时时间为 10 秒种，服务器每秒处理 50 个独立用户访问，那么系统中 Apache 的总进程数就是 10 * 50 ＝ 500 个，如果一个进程占用 4M 内存，那么总共会消耗 2G 内存，所以可以看出，在这种配置中，相当消耗内存，但好处是系统只处理了 50次 TCP 的握手和关闭操作。</p>
<p>如果关闭 KeepAlive，如果还是每秒50个用户访问，如果用户每次连续的请求数为3个，那么 Apache 的总进程数就是 50 * 3 = 150 个，如果还是每个进程占用 4M 内存，那么总的内存消耗为 600M，这种配置能节省大量内存，但是，系统处理了 150 次 TCP 的握手和关闭的操作，因此又会多消耗一些 CPU 资源。</p>
<p>在看看实践的观察。</p>
<p>我在一组大量处理动态网页内容的服务器中，起初打开 KeepAlive 功能，经常观察到用户访问量大时Apache进程数也非常多，系统频繁使用交换内存，系统不稳定，有时负载会出现较大波动。关闭了 KeepAlive 功能后，看到明显的变化是： Apache 的进程数减少了，空闲内存增加了，用于文件系统Cache的内存也增加了，CPU 的开销增加了，但是服务更稳定了，系统负载也比较稳定，很少有负载大范围波动的情况，负载有一定程度的降低；变化不明显的是：访问量较少的时候，系统平均负载没有明显变化。<br />
 <br />
总结一下：</p>
<p>在内存非常充足的服务器上，不管是否关闭 KeepAlive 功能，服务器性能不会有明显变化；<br />
如果服务器内存较少，或者服务器有非常大量的文件系统访问时，或者主要处理动态网页服务，<br />
 关闭 KeepAlive 后可以节省很多内存，而节省出来的内存用于文件系统Cache，可以提高文件系统访问的性能，并且系统会更加稳定。<br />
 <br />
补充：</p>
<p>关于是否应该关闭 KeepAlive 选项，我觉得可以基于下面的一个公式来判断。<br />
在理想的网络连接状况下，系统的 Apache 进程数和内存使用可以用如下公式表达：<br />
HttpdProcessNumber = KeepAliveTimeout * TotalRequestPerSecond / Average(KeepAliveRequests)<br />
HttpdUsedMemory = HttpdProcessNumber * MemoryPerHttpdProcess<br />
换成中文：<br />
总Apache进程数 = KeepAliveTimeout * 每秒种HTTP请求数 / 平均KeepAlive请求<br />
Apache占用内存 = 总Apache进程数 * 平均每进程占用内存数</p>
<p>需要特别说明的是：</p>
<p>[平均KeepAlive请求] 数，是指每个用户连接上服务器后，持续发出的 HTTP 请求数。当 KeepAliveTimeout 等 0 或者 KeepAlive 关闭时，KeepAliveTimeout 不参与乘的运算从上面的公式看，如果 [每秒用户请求] 多，[KeepAliveTimeout] 的值大，[平均KeepAlive请求] 的值小，都会造成 [Apache进程数] 多和 [内存] 多，但是当 [平均KeepAlive请求] 的值越大时，[Apache进程数] 和 [内存] 都是趋向于减少的。</p>
<p>基于上面的公式，我们就可以推算出当 平均KeepAlive请求 &lt;= KeepAliveTimeout 时，关闭 KeepAlive 选项是划算的，否则就可以考虑打开。</p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2009年04月1号 -- <a href="http://ourapache.com/archives/236" title="关于HTTP 协议中的 KeepAlive">关于HTTP 协议中的 KeepAlive</a></li><li>2009年02月10号 -- <a href="http://ourapache.com/archives/109" title="谈谈Apache的优化">谈谈Apache的优化</a></li><li>2009年01月5号 -- <a href="http://ourapache.com/archives/21" title="关于keepalive的解释">关于keepalive的解释</a></li></ul>
	标签：<a href="http://ourapache.com/archives/category/basic" title="Apache基础知识" rel="tag">Apache基础知识</a>, <a href="http://ourapache.com/archives/tag/keepalive" title="KeepAlive" rel="tag">KeepAlive</a><br />
]]></content:encoded>
			<wfw:commentRss>http://ourapache.com/archives/29/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>关于keepalive的解释</title>
		<link>http://ourapache.com/archives/21</link>
		<comments>http://ourapache.com/archives/21#comments</comments>
		<pubDate>Mon, 05 Jan 2009 12:59:10 +0000</pubDate>
		<dc:creator>OurApache</dc:creator>
				<category><![CDATA[Apache基础知识]]></category>
		<category><![CDATA[KeepAlive]]></category>

		<guid isPermaLink="false">http://www.ourapache.com/?p=21</guid>
		<description><![CDATA[一般来讲，http请求是一次请求完毕就关闭连接的，但是有些时候，一个apache只有少数的固定的几个或几十个机器频繁的访问，这时，每次访问都重新建立tcp连接，感觉有些无聊，这时就用到KeepAlive的相关设置了：
当KeepAlive 为 On，如果http请求头明确说明：Connection:keep-alive ;则一次请求结束后，如果该连接使用的次数没有超过MaxKeepAliveRequests ，服务器并不立即主动断开连接，而是等待KeepAliveTimeout 指定的时间,这时，如果客户端没有再发起http请求，则关闭连接；如果在KeepAliveTimeout时间内，客户端又使用该连接做http请求，则省去了重新建立tcp连接的消耗了。]]></description>
			<content:encoded><![CDATA[<div id="zoomtext" class="textbox-content">
<p><span style="font-family: Courier New;">Apache配置文件中有三个关于KeepAlive的配置指令：<br />
<span style="color: #ff0000;"><a href="http://ourapache.com/archives/tag/keepalive" class="st_tag internal_tag" rel="tag" title="标签 KeepAlive 下的日志">KeepAlive</a> On<br />
MaxKeepAliveRequests 100<br />
KeepAliveTimeout 15</span></span></p>
<p><span style="font-family: Courier New;">一般来讲，http请求是一次请求完毕就关闭连接的，但是有些时候，一个apache只有少数的固定的几个或几十个机器频繁的访问，这时，每次访问都重新建立tcp连接，感觉有些无聊，这时就用到KeepAlive的相关设置了：<br />
当<span style="color: #ff0000;">KeepAlive</span> 为 On，如果http请求头明确说明：Connection:keep-alive ;则一次请求结束后，如果该连接使用的次数没有超过<span style="color: #ff0000;">MaxKeepAliveRequests </span>，服务器并不立即主动断开连接，而是等待<span style="color: #ff0000;">KeepAliveTimeout </span><span style="color: #000000;">指定的时间,这时，如果客户端没有再发起http请求，则关闭连接；如果在<span style="color: #ff0000;">KeepAliveTimeout</span>时间内，客户端又使用该连接做http请求，则省去了重新建立tcp连接的消耗了。</span></span></p>
<p><span style="font-family: Courier New;">就上面的设置而言：</span></p>
<p><span style="font-family: Courier New;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</span></p>
<p><span style="font-family: Courier New;">如果客户端发送http请求头：</span></p>
<p><span style="font-family: Courier New;">&#8230;<br />
</span><span style="font-family: Courier New;">Connection:keep-alive<br />
</span><span style="font-family: Courier New;">&#8230;</span></p>
<p><span style="font-family: Courier New;">则服务器端相应的http头为：</span></p>
<p><span style="font-family: Courier New;">&#8230;<br />
</span><span style="font-family: Courier New;">Keep-Alive: timeout=15, max=100<br />
Connection: Keep-Alive<br />
</span><span style="font-family: Courier New;">&#8230;</span></p>
<p><span style="font-family: Courier New;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</span></p>
<p><span style="font-family: Courier New;">如果客户端发送http请求头:</span></p>
<p><span style="font-family: Courier New;">&#8230;<br />
Connection:close<br />
&#8230;</span></p>
<p><span style="font-family: Courier New;">则服务器端响应的http头为：</span></p>
<p><span style="font-family: Courier New;">&#8230;<br />
Connection:close<br />
&#8230;</span></p>
<p><span style="font-family: Courier New;">并且服务器端主动关闭连接</span></p>
<p><span style="font-family: Courier New;">================================================</span></p>
<p><span style="font-family: Courier New;">如果服务器端设置为：KeepAlive Off</span></p>
<p><span style="font-family: Courier New;">则不管客户端的http请求头如何设置，服务器端总是每次连接只处理一个请求，并立即主动关闭，响应的http头为：</span></p>
<p><span style="font-family: Courier New;">&#8230;<br />
Connection:close<br />
&#8230;</span></p>
<p><span style="font-family: Courier New;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</span></p>
<p><span style="font-family: Courier New;">下面附一段代码：</span></p>
<p><span style="color: #000000;"><span style="color: #0000bb;"><span style="font-family: Courier New;"><span style="color: #000000;"><span style="color: #0000bb;">&lt;?php<br />
main</span><span style="color: #007700;">();<br />
function </span><span style="color: #0000bb;">main</span><span style="color: #007700;">() {<br />
    </span><span style="color: #0000bb;">$host </span><span style="color: #007700;">= </span><span style="color: #dd0000;">“ljj.com”</span><span style="color: #007700;">;<br />
    </span><span style="color: #0000bb;">$port </span><span style="color: #007700;">= </span><span style="color: #0000bb;">80</span><span style="color: #007700;">;<br />
    </span><span style="color: #0000bb;">$url </span><span style="color: #007700;">= </span><span style="color: #dd0000;">“/”</span><span style="color: #007700;">;<br />
    </span><span style="color: #0000bb;">$fp </span><span style="color: #007700;">= </span><span style="color: #0000bb;">fsockopen</span><span style="color: #007700;">(</span><span style="color: #0000bb;">$host</span><span style="color: #007700;">, </span><span style="color: #0000bb;">$port </span><span style="color: #007700;">,</span><span style="color: #0000bb;">$errno</span><span style="color: #007700;">, </span><span style="color: #0000bb;">$errstr</span><span style="color: #007700;">, </span><span style="color: #0000bb;">10</span><span style="color: #007700;">);<br />
    if(</span><span style="color: #0000bb;">$fp </span><span style="color: #007700;">=== </span><span style="color: #0000bb;">false</span><span style="color: #007700;">) {<br />
        die(</span><span style="color: #0000bb;">$errstr</span><span style="color: #007700;">);<br />
    }<br />
    </span><span style="color: #0000bb;">$str </span><span style="color: #007700;">= </span><span style="color: #dd0000;">“GET / HTTP/1.1nHost: ljj.cnnConnection:keep-alivenn”</span><span style="color: #007700;">;<br />
    </span><span style="color: #0000bb;">$i </span><span style="color: #007700;">= </span><span style="color: #0000bb;">0</span><span style="color: #007700;">;<br />
    while(</span><span style="color: #0000bb;">$i</span><span style="color: #007700;">++ &lt; </span><span style="color: #0000bb;">3</span><span style="color: #007700;">) {<br />
        </span><span style="color: #0000bb;">$len </span><span style="color: #007700;">= </span><span style="color: #0000bb;">fputs</span><span style="color: #007700;">(</span><span style="color: #0000bb;">$fp</span><span style="color: #007700;">,</span><span style="color: #0000bb;">$str</span><span style="color: #007700;">);<br />
        if(</span><span style="color: #0000bb;">$len </span><span style="color: #007700;">=== </span><span style="color: #0000bb;">false</span><span style="color: #007700;">) { </span><span style="color: #ff8000;">// 这里这么判断是没有用的，因为如果服务器端单向关闭，该连接没有完全断开，则还是可以写数据的，只是没有响应而已<br />
            </span><span style="color: #007700;">die(</span><span style="color: #dd0000;">“fp errorn”</span><span style="color: #007700;">);<br />
        }<br />
        </span><span style="color: #0000bb;">$out </span><span style="color: #007700;">= </span><span style="color: #0000bb;">fread</span><span style="color: #007700;">(</span><span style="color: #0000bb;">$fp</span><span style="color: #007700;">,</span><span style="color: #0000bb;">2048</span><span style="color: #007700;">);<br />
        echo </span><span style="color: #dd0000;">“$i:$outn”</span><span style="color: #007700;">;<br />
    }<br />
    </span><span style="color: #0000bb;">fclose</span><span style="color: #007700;">(</span><span style="color: #0000bb;">$fp</span><span style="color: #007700;">);<br />
}</p>
<p></span><span style="color: #0000bb;">?&gt;</span></span></span></span></span></p>
<p><span style="color: #000000;"><span style="color: #0000bb;"><span style="color: #ff0000; font-family: Courier New;"><span style="color: #000000;"><span style="color: #0000bb;"><span style="color: #000000;">这段代码说明了多次请求可以使用同一条连接（在服务器端KeepAlive On的情况下</span>）</span></span></span></span></span></div>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2009年04月1号 -- <a href="http://ourapache.com/archives/236" title="关于HTTP 协议中的 KeepAlive">关于HTTP 协议中的 KeepAlive</a></li><li>2009年02月10号 -- <a href="http://ourapache.com/archives/109" title="谈谈Apache的优化">谈谈Apache的优化</a></li><li>2009年01月6号 -- <a href="http://ourapache.com/archives/29" title="Apache 中KeepAlive 配置的合理使用(优化) ">Apache 中KeepAlive 配置的合理使用(优化) </a></li></ul>
	标签：<a href="http://ourapache.com/archives/category/basic" title="Apache基础知识" rel="tag">Apache基础知识</a>, <a href="http://ourapache.com/archives/tag/keepalive" title="KeepAlive" rel="tag">KeepAlive</a><br />
]]></content:encoded>
			<wfw:commentRss>http://ourapache.com/archives/21/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

