构建高性能web之路------web服务器长连接
web服务器都提供长连接的方式,所谓长连接就是客户端一次请求完后,不关闭连接,保持一段时间的连接,下次此客户端再次请求时,不用创建新连接,复用所保持的连接即可。从理论上,长连接可以免去大量建立和关闭连接的资源消耗,但同时也有大量连接被占用的代价。因此可以初步判断长连接比短连接能带来更高的TPS,更低的CPU消耗,更少的IO,更高的内存占用,下面通过实战来验证。
服务器环境和测试工具可以见工具和环境准备篇
本次web服务器选用apache prefork模式,apache长短连接的选择可以配置httpd.conf里的KeepAlive选项,如:
KeepAlive On:长连接
KeepAlive Off:短连接
另外如果选择长连接还需配置KeepAliveTimeout和MaxKeepAliveRequests,其中KeepAliveTimeout为每个长连接服务端保持时长,默认配置为15秒,MaxKeepAliveRequests为每个长连接服务请求最大数,默认配置为100次,本次试验保持默认配置。
使用ab来压apache,如:
短连接环境下: /usr/alibaba/install/httpd-2.0.63-prefork/bin/ab -c 100 -n 1000000 http://localhost/
长连接环境下: /usr/alibaba/install/httpd-2.0.63-prefork/bin/ab -c 100 -n 1000000-khttp://localhost/
同时都已100个并发请求apache默认首页1000000次
然后通过ab测试结果、nmon收集资源消耗和strace跟踪实际调用三个维度来考察短连接和长连接的区别。
1)ab测试结果
短连接:
- ConcurrencyLevel:100
- Timetakenfortests:190.754776seconds
- Completerequests:1000000
- Failedrequests:0
- Writeerrors:0
- Totaltransferred:1891115351bytes
- HTMLtransferred:1456088816bytes
- Requestspersecond:5242.33[#/sec](mean)
- Timeperrequest:19.075[ms](mean)
- Timeperrequest:0.191[ms](mean,acrossallconcurrentrequests)
- Transferrate:9681.50[Kbytes/sec]received
- ConnectionTimes(ms)
- minmean[+/-sd]medianmax
- Connect:083.7844
- Processing:1103.8979
- Waiting:073.0761
- Total:4185.717101
长连接:
- ConcurrencyLevel:100
- Timetakenfortests:59.509558seconds
- Completerequests:1000000
- Failedrequests:0
- Writeerrors:0
- Keep-Aliverequests:990148
- Totaltransferred:1927566346bytes
- HTMLtransferred:1456007280bytes
- Requestspersecond:16804.02[#/sec](mean)
- Timeperrequest:5.951[ms](mean)
- Timeperrequest:0.060[ms](mean,acrossallconcurrentrequests)
- Transferrate:31631.71[Kbytes/sec]received
- ConnectionTimes(ms)
- minmean[+/-sd]medianmax
- Connect:000.1012
- Processing:0522.511406
- Waiting:0522.411405
- Total:0522.511409
从中不然发现,在其他参数和环境相同的情况下,长连接比短连接的TPS高很多,16804.02/sec vs 5242.33/sec,另外也不难发现长连接在connection上花的时间几乎为0
2)nmon的测试结果
cpu消耗:
短连接
长连接
以上数据表明长连接比短连接消耗CPU较少
IO占用:
短连接
长连接
以上数据表明长连接比短连接IO占用更少
内存空闲:
短连接
长连接
以上数据表明长连接比短连接占用更多内存
3)strace结果
apache的prefork模式是每个请求由单独的子进程来响应,因此通过对其中的一个子进程跟踪来比较调用系统资源的次数
短连接:
- %timesecondsusecs/callcallserrorssyscall
- --------------------------------------------------------------
- 44.240.187941199997accept
- 40.220.1708871017738poll
- 2.580.01097606771617737read
- 2.490.0105830599649994lstat
- 2.190.0093190499709994stat
- 1.740.007388039976setsockopt
- 1.420.00604519997shutdown
- 1.250.005312029988close
- 1.060.004499019989open
- 0.710.003003019994fcntl
- 0.570.00242609994write
- 0.450.00191109994writev
- 0.380.00159809994sendfile
- 0.350.00150309997getsockname
- 0.340.00143909997gettimeofday
- 0.000.00000212fstat
- 0.000.00000111lseek
- 0.000.00000111mmap
- 0.000.00000111munmap
- --------------------------------------------------------------
- 100.000.42483537531037725total
长连接:
- %timesecondsusecs/callcallserrorssyscall
- --------------------------------------------------------------
- 37.050.03299739919write
- 21.900.01950329940poll
- 10.380.009248039676setsockopt
- 7.860.0070000495959919stat
- 7.460.0066420595149919lstat
- 5.350.0047640497209941read
- 3.540.003156019839open
- 2.270.00201809919sendfile
- 1.950.001735019941close
- 1.280.00114309919writev
- 0.920.00081609921gettimeofday
- 0.020.0000140200fcntl
- 0.010.0000070100accept
- 0.010.0000070100getsockname
- 0.010.00000601001shutdown
- 0.000.00000212fstat
- 0.000.00000111lseek
- 0.000.00000111mmap
- 0.000.00000111munmap
- --------------------------------------------------------------
- 100.000.08906128840829780total
以上数据表明,长连接accept和shutdown次数仅为100次,而短连接为9997次,近100倍的差距,从这里就不难发现为什么长连接的TPS那么高了,省了这么多次系统调用,不快才怪啊。
本次试验得出验证来开始的理论分析:长连接比短连接能带来更高的TPS,更低的CPU消耗,更少的IO,更高的内存占用,更少的系统调用