转自:http://51write.github.io/2014/04/09/keepalive/
一个关于公众出行服务的网站欲上线,我习惯性地使用工具来检查,工具之前是yahoo的slower,因为个人较常使用chrome浏览器,最近发现google也发布了类似的插件pagespeed insights。所以借此机会实践一下。(可惜这个插件只能在美国的chrome市场才能找到)
分析结果
本篇针对常见的"启动keep-Alive"优化来阐述
关于Keep-Alive
keep-alive是http1.0与http1.1的特性之一,意在提供长效的HTTP会话,以避免客户端频繁建立tcp连接的消耗。
想象一个这样的场景:一个客户端通过页面向服务器发送request,之后两者建立一个tcp连接,伴随着返回响应信息,服务器同时将连接关闭。这个过程分为四个步骤:
-
建立tcp连接
-
发出请求文档
-
发出响应文档
-
释放tcp连接
如果此时请求的页面中含有其他的连接,比如图片、js等,客户端将重复这个过程。keep-alive的作用在于第一次建立连接时,服务器器将保持这个tcp连接一段时间(不超过设定的KeepAliveTimeout),以节省重复过程1和4创建tcp连接与释放tcp连接的时间。一般可以节省50%以上的时间。
Keep-Alive工作原理
与HTTP1.0需要主动声明不同的是,HTTP1.1默认支持这一特性,两者的交互流程如下:
HTTP1.0 Keep-Alive的数据交互流程:
-
建立tcp连接
-
Client 发出request,并声明HTTP版本为1.0,且包含header:"Connection: keep-alive"。
-
Server收到request,通过HTTP版本1.0和"Connection: keep-alive",判断连接为长连接;故Server在response的header中也增加"Connection: keep-alive"。
-
同时,Server不释放tcp连接,在Client收到response后,认定为长连接,同样也不释放tcp连接。这样就实现了会话的保持。
-
直到会话保持的时间超过keepaliveTime时,client和server端将主动释放tcp连接。
HTTP1.1 Keep-Alive的数据交互流程:
-
建立tcp连接
-
Client 发出request,并声明HTTP版本为1.1。
-
Server收到request后,通过HTTP版本1.1就认定连接为长连接;此时Server在response的header中增加"Connection: keep-alive"。
-
Server不释放tcp连接,在Client收到response后,通过"Connection: keep-alive"判断连接为长连接,同样也不释放tcp连接。
-
这个过程与http1.0类似,仅是http1.1时,客户端的request不用声明"Connection: keep-alive"。
比较
基于上述的比较,是不是采用HTTP1.1更好呢?如果不考虑浏览器并发等因素,是的。
以下的事实,仅供您参考
IE 6,7在HTTP/1.0中默认最大并发连接数为4,在HTTP/1.1中默认最大并发连接数为2,IE8都为6。Firefox2在HTTP/1.0中
默认最大并发连接数为2 在HTTP/1.1中默认最大并发连接数为8,firefox 3默认都是6。
Keep-Alive的优化
考虑一个这样的事实:
假设keepalive的时间为60s,服务器1分钟内平均在线用户为500,开启keep-Alive后,Apache等服务器的消耗为:
总进程数为500个
**假设一个进程平均占用2M的内存,总消耗内存数为500\*2=1G。**
关闭keep-alive后,Apache等服务器的消耗为:
**总进程数为500/60=10个**
**总消耗内存为10\*2=20M**
这个事实要求我们在KeepAliveTimeout、MaxKeepAliveRequests和系统资源间寻找一个平衡。
在以下的场景,不建议开启keep-alive:服务器提供的是一个接口服务,除了动态内容,几乎没有引用任何静态内容;而建议在服务器提供Web站点服务时(一个页面除了动态内容,还包含非常多的JS、图片、css文件等)开启keep-alive。
如何查询httpd进程占用的内存
pidof httpd
打印结果如下:
60257 29860 29854 29835 29834 29833 29832 29830 29829 29828 29822 29813
29812 29809 29804 29800 28051 28050 28049 28048 28047 28046 28045 28044
28042 28041 28040 28039 28038 28037 28036 28020 28008 28007 28006 28002
28001 27999 27980 27978 27402 27396 27375 27292 24414 24413 24412 24405
24032 24023 24018 24017 24015 24014 24010 24006 23572 23554 23553 23552
23530 23526 23523 23514 23512 23505 23499 23496 23494 23493 23491 23489
23487 23482 23481 23479 23476 23475 23474 23473 23472 23471 23468 23461
23443 23442 23441 23440 23439 23438 23434 23281 23177 23176 23175 23174
23170 23169 23166 23023 22969 22721 22720 22719 22718 22717 22716 22715
22714 22713 22712 22711 22710 22709 22708 22707 22706 22705 22704 22703
22702 22701 22700 22699 22698 22697 22696 22695 22694 22693 22692 22691
22690 22689 22688 22687 22686 22685 22684 22683 22682 22681 22680 22679
22678 22677 22676 22675 22674 22673 22672 22671 22670 22669 22668 22667
22666 22662 22661 22660 22659 22658 22657 22656 22655 22654 22653 22652
22651 22650 22649 22648 22647 22646 22645 22644 22643 22642 22641 22640
22639 22638
查看任意进程占用的内存
top -p 60257或者
cat /proc/60257/status
打印结果分别为
top - 18:51:38 up 480 days, 5:16, 4 users, load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie Cpu(s):
0.1%us, 0.1%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem:
32909664k total, 30598768k used, 2310896k free, 560268k buffers Swap:
34996220k total, 864k used, 34995356k free, 21710184k cached
PID USER PR NI VIRT **RES** SHR S %CPU %MEM TIME+ COMMAND
22670 apache 20 0 558m 106m 1720 S 0.0 0.3 0:00.06 httpd
结果中的RES 106m,和下面的VMRSS 108964 kB结果都一样。
sched sessionid stack statm syscall
schedstat smaps stat status
[developer01@cqjt-middle02 ~]\$ cat /proc/22670/s sched sessionid stack
statm syscall
schedstat smaps stat status
[developer01@cqjt-middle02 ~]\$ cat /proc/22670/status Name: httpd State: S
(sleeping) Tgid: 22670 Pid: 22670 PPid: 60257 TracerPid: 0 Uid: 48 48 48 48
Gid: 48 48 48 48 Utrace: 0 FDSize: 64 Groups: 48 VmPeak: 571720 kB
VmSize: 571716 kB VmLck: 0 kB VmPin: 0 kB VmHWM: 108964 kB
**VmRSS: 108964 kB** VmData: 182768 kB VmStk: 136 kB VmExe: 336 kB
VmLib: 29772 kB VmPTE: 756 kB VmSwap: 0 kB Threads: 1
SigQ: 0/256954 SigPnd: 0000000000000000 ShdPnd: 0000000000000000
SigBlk: 0000000000000000 SigIgn: 0000000000001000 SigCgt: 00000001880046eb
CapInh: 0000000000000000 CapPrm: 0000000000000000 CapEff: 0000000000000000
CapBnd: ffffffffffffffff Cpus_allowed: ffffffff,ffffffff
Cpus_allowed_list: 0-63
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000003
Mems_allowed_list: 0-1 voluntary_ctxt_switches: 445
nonvoluntary_ctxt_switches: 0
HTTPD占用的内存非常大的,有100M之多,也就是说,可以使用1G内存的服务器,我们最多也只能设置MaxKeepAliveRequests为10。
而KeepAliveTimeout的设定则以单个页面资源加载时间为准,比如出行的用户,页面请求资源的时间大约为2s,所以我们设定这个值为2秒。
如何开启Keep-Alive
Apache http Server
修改httpd.conf文件
KeepAlive On
MaxKeepAliveRequests 300
重新启动
apachectl -k graceful
Nginx
不同于apache,nginx本身仅支持一个keepalive_timeout 指令,其使用0值来停用keep-alive。
在http、server、location指令中添加指令
location /cqjt/ {
alias /url/var/www/html/;
keepalive_timeout 75;
expires 5m;
}
总结
大多数时候,是否能保存长连接以及设定长连接的时间,并不由服务器决定,有时浏览器(比如火狐等),其默认60秒后自动断开任何长连接。这时服务器的tomeout时间将失效。