Apache服务器访问过慢分析及解决.docx
《Apache服务器访问过慢分析及解决.docx》由会员分享,可在线阅读,更多相关《Apache服务器访问过慢分析及解决.docx(68页珍藏版)》请在冰豆网上搜索。
Apache服务器访问过慢分析及解决
Apache服务器访问过慢分析及解决
起因:
线上的一台服务器,最近总是出现访问很慢的情况发生,点击一个链接要2秒钟以上才能打开,按照我们对于访问人数的估计,服务器应该不至于响应这么慢,从而需要针对这个问题进行分析,来解决网站访问过慢。
分析:
1、首先,在页面访问变慢情况发生时,使用top命令查看了服务器的负载情况,发现负载并不高,初步估计不是程序的问题。
2、然后,查看了线程中的httpd的数量,ps-aux|grephttpd|wc-l发现,线程数已经达到了apache设置的最大值。
由此断定是网站访问人数过多造成了访问过慢。
3、为了验证,查看了连接数和当前的连接数,分别是
netstat-ant|grep$ip:
80|wc-l
netstat-ant|grep$ip:
80|grepEST|wc-l
发现果然,连接数特别多,远远超过我们的估计值。
4、刚开始的时候,对于服务器的MPM配置方式不是特别的熟悉,认为修改服务器配置可以解决问题。
主要的配置部分包括prefork模式或者work模式的配置,下面是一些简单的介绍。
prefork模式:
以prefork模式工作的apache的默认配置:
ServerLimit 2000
StartServers 5 #指定服务器启动时建立的子进程数量
MinSpareServers 5 #指定空闲子进程的最小数量
MaxSpareServers 10 #指定空闲子进程的最大数量
MaxClients 150 #指定同一时间客户端最大接入请求的数量(单个进程并发线程数),任何超过该限制的请求都将进入等候队列,一旦一个连接被释放,队列中的请求将得到服务
MaxRequestsPerChild 0 #指定每个子进程在其生存周期内允许伺服的最大请求数量,默认为10000,0表示子进程永远不结束
prefork控制进程在最初建立“StartServers”个子进程后,为了满足MinSpareServers设置的需要创建一个进程,等待一秒钟,继续创建两个,再等待一秒钟,继续创建四个……如此按指数级增加创建的进程数,最多达到每秒32个,直到满足MinSpareServers设置的值为止。
这种模式可以不必在请求到来时再产生新的进程,从而减小了系统开销以增加性能。
MaxSpareServers设置了最大的空闲进程数,如果空闲进程数大于这个值,Apache会自动kill掉一些多余进程。
这个值不要设得过大,但如果设的值比MinSpareServers小,Apache会自动把其调整为MinSpareServers+1。
如果站点负载较大,可考虑同时加大MinSpareServers和MaxSpareServers。
MaxClients是这些指令中最为重要的一个,设定的是Apache可以同时处理的请求,是对Apache性能影响最大的参数。
其缺省值150是远远不够的,如果请求总数已达到这个值(可通过ps-ef|grephttpd|wc-l来确认),那么后面的请求就要排队,直到某个已处理请求完毕。
这就是系统资源还剩下很多而HTTP访问却很慢的主要原因。
虽然理论上这个值越大,可以处理的请求就越多,但Apache默认的限制不能大于256。
在apache2中通过ServerLimit指令无须重编译Apache就可以加大MaxClients。
虽然通过设置ServerLimit,我们可以把MaxClients加得很大,但是往往会适得其反,系统耗光所有内存。
以一台服务器为例:
内存2G,每个apache进程消耗大约0.5%(可通过psaux来确认)的内存,也就是10M,这样,理论上这台服务器最多跑200个apache进程就会耗光系统所有内存,所以,设置MaxClients要慎重。
worker模式:
以worker模式工作的apache的默认配置为:
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
Worker由主控制进程生成“StartServers”个子进程,每个子进程中包含固定的ThreadsPerChild线程数,各个线程独立地处理请求。
同样,为了不在请求到来时再生成线程,
MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数;而MaxClients设置了同时连入的clients最大总数。
如果现有子进程中的线程总数不能满足负载,控制进程将派生新的子进程。
MinSpareThreads和MaxSpareThreads的最大缺省值分别是75和250。
这两个参数对Apache的性能影响并不大,可以按照实际情况相应调节。
ThreadsPerChild是workerMPM中与性能相关最密切的指令。
ThreadsPerChild的最大缺省值是64,如果负载较大,64也是不够的。
这时要显式使用ThreadLimit指令,它的最大缺省值是20000。
Worker模式下所能同时处理的请求总数是由子进程总数乘以ThreadsPerChild值决定的,应该大于等于MaxClients。
如果负载很大,现有的子进程数不能满足时,控制进程会派生新的子进程。
默认最大的子进程总数是16,加大时也需要显式声明ServerLimit(最大值是20000)。
需要注意的是,如果显式声明了ServerLimit,那么它乘以ThreadsPerChild的值必须大于等于MaxClients,而且MaxClients必须是ThreadsPerChild的整数倍,否则Apache将会自动调节到一个相应值。
服务器的apache采用的是prefork的工作模式,对MaxClients进行了相应的调整,发现服务启动后很短时间,连接数就能够达到最大。
5、后来想到需要查看用户都是访问的那些页面,将配置中的access_log打开,发现85%以上的访问都是直接访问的资源文件,由此判定,用户可能使用了多线程的下载工具,或者这些资源遭受了盗链。
6、找到了问题所在,进行解决也就比较好办了。
想到了两个方法:
A、对单个IP进行连接的线程限制,不允许多线程连接资源。
对于IP限制,我采用了mod_limitipconn这个模块。
这个模块的好处是比较简单,缺点是不能够针对单独的文件夹或者文件进行设置,而且不支持虚拟主机。
在apache中安装了这个模块后,在配置文件中添加如下几段就可以生效了:
ExtendedStatusOn
#所有虚拟主机的/目录
MaxConnPerIP3 #每IP只允许3个并发连接
NoIPLimitimage/* #对图片不做IP限制
#所有主机的/mp3目录
MaxConnPerIP1 #每IP只允许一个连接请求
OnlyIPLimitaudio/mpegvideo #该限制只对视频和音频格式的文件
B、添加URL重写,防止盗链。
防止盗链,一个重要的方法就是判断请求的refer,但是如果使用一些浏览器发出请求的时候将refer去掉,或者伪装,这个办法就无能为力了。
但是貌似还有更高级的方法,还是可以实现这个功能。
安装apache的mod_rewrite模块后,在apache配置文件中添加
RewriteEngineOn
RewriteCond%{HTTP_REFERER}!
^[NC]
RewriteCond%{HTTP_REFERER}!
^$[NC]
RewriteCond%{HTTP_REFERER}!
^[NC]
RewriteCond%{HTTP_REFERER}!
^$[NC]
RewriteRule.*\.(gif|jpg|swf)$ [R,NC]
这样盗链的请求会被重定向到一个错误页面,从而减少下载带给服务器的压力。
参考资料:
1、部署Apache的一些技巧。
2、ApacheServer负载能力测试
3、ApacheAB
4、Apache的参数设置
5、Ab的用法
6、Apache限制连接数和并发数
7、Apache安装mod_rewrite模块
8、Apache防盗链的简单实现
Windows系统下如果优化Apache的性能主要是通过专门针对WindowsNT优化的MPM(多路处理模块)-mpm_winnt.c来优化的,它使用一个单独的父进程产生一个单独的子进程,在这个子进程中轮流产生多个线程来处理请求。
也就是说mpm_winnt只能启动父子两个进程,不能像Linux下那样同时启动多个进程。
mpm_winnt主要通过ThreadsPerChild和MaxRequestsPerChild两个参数来优化Apache。
ThreadsPerChild这个参数用于设置每个进程的线程数,子进程在启动时建立这些线程后就不再建立新的线程了.一方面因为mpm_winnt不能启动多个进程,所以这个数值要足够大,以便可以处理可能的请求高峰;另一方面该参数以服务器的响应速度为准的,数目太大的反而会变慢。
因此需要综合均衡一个合理的数值。
mpm_winnt上的默认值是64,最大值是1920.这里建议设置为100-500之间,服务器性能高的话值大一些,反之值小一些。
MaxRequestsPerChild该参数表示每个子进程能够处理的最大请求数,即同时间内子进程数目.设置为零表示不限制,mpm_winnt上的默认值就是0.官方参考手册中不建议设置为0,主要基于两点考虑:
(1)可以防止(偶然的)内存泄漏无限进行,从而耗尽内存;
(2)给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。
因此这个参数的值更大程度上取决于服务器的内存,如果内存比较大的话可以设置为0或很大的数字,否则设置一个小的数值。
需要说明的是,如果这个值设置的太小的话会造成Apache频繁重启,在日志文件中会看到如下的文字:
ProcessexitingbecauseitreachedMaxRequestsPerChild.Signalingtheparent,这样一来降低了Apache的总体性能。
另外,可以通过查看Apache提供的server-status(状态报告)来验证当前所设置数值是否合理,在httpd.conf文件中做如下设置来打开它:
#首先需要加载mod_status模块LoadModulestatus_modulemodules/mod_status.so#然后设置访问的地址SetHandlerserver-statusOrderdeny,allowDenyfromall#如果限制某个IP访问则设置为Allowfrom192.168.1.1Allowfromall综合来说,因为WindowsNT下Apache只能启动父子两个进程,因此只能通过增大单个进程的线程数以及单个进程能够处理的最大请求数来进行优化。
其他优化的参数同Linux系统下是一样的,大家可以加以参考。
下面针对上述两个参数给出一个建议的设置:
ThreadsPerChild250MaxRequestsPerChild5000用上面的方法优化了一下windows+apache+php后,发现响应速度快了很多,一般最多只延迟3秒左右,但对于美国的主机来说应该是个正常的状态吧!
大型网站HTTPS实践三:
基于协议和配置的优化
1前言
上文讲到 HTTPS对用户访问速度的影响。
本文就为大家介绍HTTPS在访问速度,计算性能,安全等方面基于协议和配置的优化。
2HTTPS访问速度优化
2.1Tcpfastopen
HTTPS和HTTP使用TCP协议进行传输,也就意味着必须通过三次握手建立TCP连接,但一个RTT的时间内只传输一个syn包是不是太浪费?
能不能在syn包发出的同时捎上应用层的数据?
其实是可以的,这也是tcpfastopen的思路,简称TFO。
具体原理可以参考rfc7413。
遗憾的是TFO需要高版本内核的支持,linux从3.7以后支持TFO,但是目前的windows系统还不支持TFO,所以只能在公司内部服务器之间发挥作用。
2.2HSTS
前面提到过将用户HTTP请求302跳转到HTTPS,这会有两个影响:
1、不安全,302跳转不仅暴露了用户的访问站点,也很容易被中间者支持。
2、降低访问速度,302跳转不仅需要一个RTT,浏览器执行跳转也需要执行时间。
由于302跳转事实上是由浏览器触发的,服务器无法完全控制,这个需求导致了HSTS的诞生:
HSTS(HTTPStrictTransportSecurity)。
服务端返回一个HSTS的httpheader,浏览器获取到HSTS头部之后,在一段时间内,不管用户输入还是,都会默认将请求内部跳转成。
Chrome,firefox,ie都支持了HSTS(
2.3Sessionresume
Sessionresume顾名思义就是复用session,实现简化握手。
复用session的好处有两个:
1、减少了CPU消耗,因为不需要进行非对称密钥交换的计算。
2、提升访问速度,不需要进行完全握手阶段二,节省了一个RTT和计算耗时。
TLS协议目前提供两种机制实现sessionresume,分别介绍一下。
2.3.1Sessioncache
Sessioncache的原理是使用clienthello中的sessionid查询服务端的sessioncache,如果服务端有对应的缓存,则直接使用已有的session信息提前完成握手,称为简化握手。
Sessioncache有两个缺点:
1、需要消耗服务端内存来存储session内容。
2、目前的开源软件包括nginx,apache只支持单机多进程间共享缓存,不支持多机间分布式缓存,对于XX或者其他大型互联网公司而言,单机sessioncache几乎没有作用。
Sessioncache也有一个非常大的优点:
sessionid是TLS协议的标准字段,市面上的浏览器全部都支持sessioncache。
XX通过对TLS握手协议及服务器端实现的优化,已经支持全局的sessioncache,能够明显提升用户的访问速度,节省服务器计算资源。
2.3.2Sessionticket
上节提到了sessioncache的两个缺点,sessionticket能够弥补这些不足。
Sessionticket的原理参考RFC4507。
简述如下:
server将session信息加密成ticket发送给浏览器,浏览器后续握手请求时会发送ticket,server端如果能成功解密和处理ticket,就能完成简化握手。
显然,sessionticket的优点是不需要服务端消耗大量资源来存储session内容。
Sessionticket的缺点:
1、sessionticket只是TLS协议的一个扩展特性,目前的支持率不是很广泛,只有60%左右。
2、sessionticket需要维护一个全局的key来加解密,需要考虑KEY的安全性和部署效率。
总体来讲,sessionticket的功能特性明显优于sessioncache。
希望客户端实现优先支持sessionticket。
2.4Ocspstapling
Ocsp全称在线证书状态检查协议(rfc6960),用来向CA站点查询证书状态,比如是否撤销。
通常情况下,浏览器使用OCSP协议发起查询请求,CA返回证书状态内容,然后浏览器接受证书是否可信的状态。
这个过程非常消耗时间,因为CA站点有可能在国外,网络不稳定,RTT也比较大。
那有没有办法不直接向CA站点请求OCSP内容呢?
ocspstapling就能实现这个功能。
详细介绍参考RFC6066第8节。
简述原理就是浏览器发起clienthello时会携带一个certificatestatusrequest的扩展,服务端看到这个扩展后将OCSP内容直接返回给浏览器,完成证书状态检查。
由于浏览器不需要直接向CA站点查询证书状态,这个功能对访问速度的提升非常明显。
Nginx目前已经支持这个ocspstaplingfile,只需要配置ocspstaplingfile的指令就能开启这个功能:
∙ssl_staplingon;ssl_stapling_fileocsp.staple;
2.5Falsestart
通常情况下,应用层数据必须等完全握手全部结束之后才能传输。
这个其实比较浪费时间,那能不能类似TFO一样,在完全握手的第二个阶段将应用数据一起发出来呢?
google提出了falsestart来实现这个功能。
详细介绍参考https:
//tools.ietf.org/html/draft-bmoeller-tls-falsestart-00。
简单概括Falsestart的原理就是在client_key_exchange发出时将应用层数据一起发出来,能够节省一个RTT。
Falsestart依赖于PFS(perfectforwardsecrecy完美前向加密),而PFS又依赖于DHE密钥交换系列算法(DHE_RSA,ECDHE_RSA,DHE_DSS,ECDHE_ECDSA),所以尽量优先支持ECDHE密钥交换算法实现falsestart。
2.6使用SPDY或者HTTP2
SPDY是google推出的优化HTTP传输效率的协议(https:
//www.chromium.org/spdy),它基本上沿用了HTTP协议的语义,但是通过使用帧控制实现了多个特性,显著提升了HTTP协议的传输效率。
SPDY最大的特性就是多路复用,能将多个HTTP请求在同一个连接上一起发出去,不像目前的HTTP协议一样,只能串行地逐个发送请求。
Pipeline虽然支持多个请求一起发送,但是接收时依然得按照顺序接收,本质上无法解决并发的问题。
HTTP2是IETF2015年2月份通过的HTTP下一代协议,它以SPDY为原型,经过两年多的讨论和完善最终确定。
本文就不过多介绍SPDY和HTTP2的收益,需要说明两点:
1、SPDY和HTTP2目前的实现默认使用HTTPS协议。
2、SPDY和HTTP2都支持现有的HTTP语义和API,对WEB应用几乎是透明的。
Google宣布chrome浏览器2016年将放弃SPDY协议,全面支持HTTP2,但是目前国内部分浏览器厂商进度非常慢,不仅不支持HTTP2,连SPDY都没有支持过。
XX服务端和XX手机浏览器现在都已经支持SPDY3.1协议。
3HTTPS计算性能优化
3.1优先使用ECC
ECC椭圆加密算术相比普通的离散对数计算速度性能要强很多。
下表是NIST推荐的密钥长度对照表。
表格2NIST推荐使用的密钥长度
对于RSA算法来讲,目前至少使用2048位以上的密钥长度才能保证安全性。
ECC只需要使用224位长度的密钥就能实现RSA2048位长度的安全强度。
在进行相同的模指数运算时速度显然要快很多。
3.2使用最新版的openssl
一般来讲,新版的openssl相比老版的计算速度和安全性都会有提升。
比如openssl1.0.2采用了intel最新的优化成果,椭圆曲线p256的计算性能提升了4倍。
(https:
//eprint.iacr.org/2013/816.pdf)
Openssl2014年就升级了5次,基本都是为了修复实现上的BUG或者算法上的漏洞而升级的。
所以尽量使用最新版本,避免安全上的风险。
3.3硬件加速方案
现在比较常用的TLS