Nginx性能优化
一、性能优化概述
做事有做事的原则,解决问题有解决问题的方法,那我们在做性能优化工作之前也同样要有自己的逻辑,我们为什么要做优化,我们需要重点考虑哪些方面,和了解哪些方面呢?在南汐看来,一切优化工作的目的就是基于业务稳定安全的前提下尽可能的提高用户的访问体验。
1、首先我们需要了解当前系统的结构和瓶颈,当我们的脑袋里存在一个明确的业务框架逻辑时,那么我们对于就会有一个明确的方向。比如了解我们公司当前使用的是什么,运行的是什么业务,都有哪些服务,了解每个服务最大可支撑多少并发,能支持多少qps(每秒查询率)的访问请求,这组系统的最高瓶颈在哪里?(我们如何评定我们系统的瓶颈呢,例如使用top查看系统的CPU负载、内存使用率、总得运行进程等,也可以通过日志去分析请求的情况,也可以通过我们前面介绍到的stub_statius模块查看当前的连接情况,对线上的业务进行压力测试【低峰期】,去了解当前这套系统能承担多少的请求和并发,做好响应的评估。这个是我们做性能优化最先考虑的地方。)
2、了解业务模式。性能优化是为业务服务的,本质上就是提高业务能力。我们需要了解每个业务接口的类型,比如:电商网站中的抢购模式,这种情况下面,平时没什么流量,但到了抢购时间流量会突增。我们还需要了解系统层次化的结构,比如:我们使用nginx做的是代理、还是动静分离、还是后端直接服务用户,我们要对每一层做好相应的梳理,以便更好的服务业务。
3、性能与安全。通常会有这样一个情况,我们往往注重了性能,但是忽略了安全,往往过于注重安全,对性能又会产生影响。比如:我们在设计防火墙功能时,检测过于严密,这样就会给性能带来影响。那么如果对于性能完全追求,却不顾服务的安全,也会造成很大的隐患。我们需要评估好两者的关系,把握好两者的孰重孰轻。以及整体的相关性,权衡好对应的点。
二、压力测试工具
1 | [root@web1 ~]#yum -y install httpd-tools |
我们可以先以自己的静态网页为例(现在很多的网站基本都会设置屏蔽外界压测),来做一个小测试:
1 | [root@web1 ~]#ab -k -c100 -n1000 http://nanxi.com/ |
三、性能优化
1、系统性能优化
文件句柄,Linux一切皆文件,文件句柄可以理解为就是一个索引,文件句柄会随着我们进程的调用频繁增加,系统默认文件句柄是有限制的,不能让一个进程无限的调用,所以我们需要限制每个进程和每个服务使用多大的文件句柄
1 | [root@lb01 ~]# vim /etc/security/limits.conf |
在高并发短连接的TCP服务器上,当服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量socket处于TIME_WAIT状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上。
为什么我们要关注这个高并发短连接呢?高并发可以让服务器在短时间范围内同时占用大量端口,而端口有个0~65535的范围,并不是很多,除去系统和其他服务要用的,剩下的就更少了。在这个场景中,短连接表示业务处理+传输数据的时间远远小于 TIMEWAIT超时的时间的连接。比如取一个web页面,1秒钟的http短连接处理完业务,在关闭连接之后,这个业务用过的端口会停留在TIMEWAIT状态几分钟,而这几分钟,其他HTTP请求来临的时候是无法占用此端口的。。单用这个业务计算服务器的利用率会发现,服务器干正经事的时间和端口(资源)被挂着无法被使用的时间的比例是 1:几百,服务器资源严重浪费。(在实际业务场景中,一般长连接对应的业务的并发量并不会很高。)
2、代理服务优化
通常nginx作为代理服务,负责转发用户的请求,那么在转发的过程中建议开启HTTP长连接,用于减少握手次数,降低服务器损耗。
1 | upstream backend { |
对于fastcgi服务器,需要设置fastcgi_keep_conn以便保持长连接
1 | upstream fastcgi_backend { |
scgi和uwsgi协议没有保持连接的概念,但无论是proxy、fastcgi、uwsgi协议都有cache缓存的功能,开启后可加速网站访问的效率(取决硬件)。
3、静态资源优化
静态资源指的是非WEB服务器端运行处理而生成的文件:
静态资源类型 | 种类 |
---|---|
浏览器渲染 | HTML、CSS、JS… |
图片文件 | JPEG、GIF、PNG… |
视频文件 | FLV、Mp4、AVI… |
其他文件 | TXT、DOC、PDF… |
浏览器缓存设置用于提高网站性能,尤其是新闻网站,图片一旦发布,改动的可能是非常小的,所以我们希望能否用户访问一次后,图片缓存在用户的浏览器长时间缓存。 浏览器是有自己的缓存机制,他是基于HTTP协议缓存机制来实现的,在HTTP协议中有很多头信息,那么实现浏览器的缓存就需要依赖特殊的头信息来与服务器进行特殊的验证,如Expires(http/1.0);Cache-control(http/1.1)
浏览器缓存过期校验机制:
1、浏览器请求服务器会先进行Expires、Cache-Control的检查,检查缓存是否过期,如果没有过期则直接从缓存文件中读取。
2、如果缓存过期首先检查是否存在etag,如果存在那么客户端会向web服务器请求If-None-Match,与etag值进行比对,有服务器决策返回200还是304。
3、如果etag不存在,则进行last-Modified检查,客户端会向web服务器请求if-Modified-Since,与last-Modified进行比对,有服务器决策返回200还是304。Last-Modified:服务器上文件的最后修改时间
Etag:文件标识
Expires:本地缓存目录中,文件过期的时间(由服务器指定具体的时间)
Cache-control:本地缓存目录中,文件过期的时间(由服务器指定过期的间隔时间,由于浏览器根据间隔生成具体的时间)
1 | ### 配置静态资源缓存场景 |
文件读取高效sendfile,如下图
1 | Syntax: sendfile on | off; |
将多个包一次发送,用于提升网络传输效率,大文件推荐打开,需要开启sendfile才行
1 | Syntax: tcp_nopush on | off; |
提高网络传输实时性,需要开启keepalive,来一个包发一个包不等待行
1 | Syntax: tcp_nodelay on | off; |
静态资源压缩 ★★★
1 | location ~ .*\.(jpg|png|gif) { |
注意:gzip对于压缩图片的比率不太明显,但对于文件的压缩,655K可以压缩到153K压缩的比率很高。
四、防止资源盗链
1 | Syntax: valid_referers none | blocked | server_name | string ...; |
1 | location ~ .*\.(jpg|png|gif) { |
当然这种防护并不能百分百保证资源不被盗链,因为我们可以通过命令来修改来源的refer信息
1 | # 伪造协议头访问,因为大多时候我们不会禁止搜索引擎盗链,我们反而需要他们收录我们的信息。 |
五、CPU亲和配置
CPU亲和(affinity)减少进程之间不断频繁切换,减少性能损耗,其实现原理是建CPU核心和Nginx工作进程绑定方式,把每个worker进程固定到对应的cpu上执行,减少切换CPU的cache miss,获得更好的性能。
1 | ### 核心模块中配置 |
1 | user www; # nginx进程启动用户 |