【高并发解决方案】Apache服务器性能调优

这个往往并不是最重要的,服务器的计算瓶颈可以通过简单线性扩充来解决,在生产环境中大多数集群服务器的瓶颈都在数据库上,如果其它瓶颈都得以解决,倒是可以考虑下服务器本身的性能调优了。

性能调优是为了充分利用自身硬件资源,主要是CPU、内存和带宽,硬盘一般不用考虑。特别是多核CPU,要使程序充分利用每个核心。

首先来看看Apache的工作模式。
这里只谈及Apache的版本分支2.2.x和最新版2.4.x
这两个apache版本区别和用法不赘述,想了解可以查阅官方文档。简单来说,追求稳定就用2.2.x,追求速度就用2.4.x

2.2.x默认的工作模式是prefork,2.4.x默认的工作模式是worker
首先说下prefork,因为它是多进程的,每个web请求互不影响,所以非常稳定,缺点是耗内存,进程多了CPU上下文切换也吃力。
prefork默认的参数配置是:
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
</IfModule>
这些参数值都比较低,大概是针对单核1G内存的服务器。
如果你使用硬件配置更好的服务器,这些参数就需要适当调大一些。
有人说我把每个参数都调得很大不就行了吗?也不是不可以,你喜欢咯,某些情况下说不定还真的是简单管用。但往往也会适得其反,比如耗尽CPU或者耗尽内存影响其他业务,所以不能盲目。

至于如何确定每个参数,这里不得不提一下apache自带的压测工具ab
先来看个例子:
/usr/local/apache2/bin/ab -k -c 1000 -n 10000 localhost/

这条命令执行后 每秒向 localhost/ 发送1000个请求,总共10000个请求。测试结果如下:

Server Software: Apache/2.2.31
Server Hostname: localhost
Server Port: 80

Document Path: /
Document Length: 425 bytes

Concurrency Level: 1000
Time taken for tests: 3.548 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Keep-Alive requests: 10000
Total transferred: 6654631 bytes
HTML transferred: 4272100 bytes
Requests per second: 2818.72 [#/sec] (mean)
Time per request: 354.771 [ms] (mean)
Time per request: 0.355 [ms] (mean, across all concurrent requests)
Transfer rate: 1831.79 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 6.7 0 82
Processing: 6 71 82.2 58 2971
Waiting: 5 71 82.2 58 2971
Total: 6 72 83.0 58 2991

Percentage of the requests served within a certain time (ms)
50% 58
66% 74
75% 86
80% 94
90% 119
95% 156
98% 251
99% 315
100% 2991 (longest request)
测试结束后就可以查看测试的统计信息,如果时间足够,可以测试多几次,我们来重点分析几个参数:
Concurrency Level:1000
该次测试的并发为1000

Requests per second: 2818.72 [#/sec] (mean)
web服务器每秒处理的请求数,这里约为2819个。

Transfer rate: 1831.79 [Kbytes/sec] received
传输速率,根据这个你可以确认服务器的带宽是否足够

Time per request: 354.771 [ms] (mean)
Percentage of the requests served within a certain time (ms)
99% 315
这个主要看99%的值,上面测试结果99%的请求都在313毫秒内完成。

通过上面的压测数据,如果每个请求的业务逻辑都跟压测的请求差不多的话,假设每个用户每秒发生一次请求,那么可以做一个粗略的评估:
当前web服务器能够同时服务2818个用户,并保证99%的用户体验的响应时间在0.3秒以内(排除网络通讯等各种复杂环境造成的延迟)。
请求的业务逻辑稍微复杂一些的话,并发量会急剧下降。但通过这些简单测试,我们大概还是可以了解服务器的处理能力。

而这里我们只测试一个请求,实际环境中,并发时用户会请求各种各样的请求,比如登录、访问主页、进行资料更改…等等一系列操作。这时我们就要找出核心的业务流程,通过脚本来实现压测,才能真正模拟上线环境,这里以后再说。

测试过程中我们还要观察记录服务器的CPU和内存使用状况,最简单的办法是开启两个终端,一个用于压测,一个用于监控。

这时你可能会发现,即使是上面的压测过程中,服务器也可能没有充分利用硬件资源。整个压测过程中CPU可能都处在50%,内存也剩很多,貌似一点压力都没有,但为什么并发量并没有上去呢?
这些情况由各种各样的瓶颈造成,包括数据库太慢导致很多请求都在空转,锁竞争等等…还有一个原因可能是apache的配置参数限制了并发量。
压测过后,查看apache错误日志,如果出现日志:
apache server reached MaxClients setting, consider raising the MaxClients setting
基本上就是提醒你要调优了。
我们通过逐步调大apache的最大服务进程,再压测确定合适的值,一般让CPU达到85%,内存占用85%就不错了。这里要注意,不要耗尽服务器的CPU和内存,这会导致即使apache用足够的内存开启进程,但是web程序却没有内存处理用户请求。
在centos下可以通过以下命令查看压测时的链接状态
netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’
我们清晰看到服务器当前的请求数和请求状态,便于我们分析服务器承受的压力。

再说worker模式,它的特点是多进程多线程混合,可以简单理解为:在prefork的基础上,再在每条进程开辟多条线程处理用户请求。假设有100个用户请求,在prefork模式下就可能会创建100条进程对分别对应每个用户,如果某个进程崩溃了只会影响一个用户。而在worker模式下,apache可能只会创建5条进程,每个进程开启20条线程,每个线程对应一个用户请求,这样消耗资源更少,但是某一条进程崩溃了的话,进程下的线程全部受影响。而且worke工作模式要求每个线程是安全的,PHP下有些模块就不是线程安全的,在worker模式下运作不够稳定。网站如果使用PHP出现请求崩溃问题,建议使用稳定的prefork工作模式。
这个模式下调优方法跟上面的差不多,主要是合理配置子线程数。

【2017-2-18 16:48:41】

发表评论

电子邮件地址不会被公开。 必填项已用*标注