Nginx性能优化概述
基于Nginx性能优化,那么在性能优化这一章,我们将分为如下几个方面做介绍
1.首先我们需要了解性能优化要考虑哪些方面。
2.然后我们需要了解性能优化必须要用到的压力测试工具ab。
3.最后我们需要了解系统上有哪些注意和优化的点,以及Nginx配置文件。
我们在做性能优化工作前,我们重点需要考虑哪些方面和了解哪些方面。
1.首先需要了解我们当前系统结构和瓶颈,了解当前使用的是什么,运行的是什么业务,都有哪些服务,了解每个服务最大能支撑多大并发。比如Nginx作为静态资源服务的并发是多少,最高瓶颈在哪里,能支持多少qps(每秒查询率)的访问请求,那我们怎么得出这组系统结构瓶颈呢,比如top查看系统的cpu负载、内存使用率、总的运行进程等,也可以通过日志去分析请求的情况,当然也可以通过我们前面介绍到的stub_status模块查看当前的连接情况,也可以对线上的业务进行压力测试(低峰期),去了解当前这套系统能承担多少的请求和并发,已做好相应的评估。这个是我们做性能优化最先考虑的地方。
2.其次我们需要了解业务模式,虽然我们是做性能优化,但每一个性能的优化都是为业务所提供服务的,我们需要了解每个业务接口的类型,比如:电商网站中的抢购模式,这种情况下面,平时没什么流量,但到了抢购时间流量会突增。我们还需要了解系统层次化的结构,比如: 我们使用Nginx做的是代理、还是动静分离、还是后端直接服务用户,那么这个就需要我们对每一层做好相应的梳理。以便更好的服务业务。
3.最后我们需要考虑性能与安全,往往注重了性能,但是忽略了安全。往往过于注重安全,性能又会产生影响。比如:我们在设计防火墙功能时,检测过于严密,这样就会给性能带来影响。那么如果对于性能完全追求,却不顾服务的安全,这个也会造成很大的隐患,所以需要评估好两者的关系,把握好两者的孰重孰轻。以及整体的相关性,权衡好对应的点。
在做性能优化前, 我们需要对如下进行考虑
1.当前系统结构瓶颈
观察指标
压力测试
2.了解业务模式
接口业务类型
系统层次化结构
3.性能与安全
性能好安全弱
安全好性能低
一、 压力测试工具实战
1.安装压力测试工具ab
[root@qiudao ~]# yum install httpd-tools -y
2.了解压测工具使用方式
[root@qiudao ~]# yum install httpd-tools -y
#-n总的请求次数
#-c并发请求数
3.使用ab工具进行压力测试
[root@web01 /etc/nginx]# ab -n2000 -c2 http://127.0.0.1/test.html
....
Server Software: nginx/1.16.1
Server Hostname: 127.0.0.1
Server Port: 80
Document Path: /test.html
Document Length: 153 bytes
Concurrency Level: 2
Time taken for tests: 0.191 seconds #总花费总时长
Complete requests: 2000 #总请求数
Failed requests: 0 #请求失败数
Write errors: 0
Non-2xx responses: 2000
Total transferred: 606000 bytes #总传输大小
HTML transferred: 306000 bytes #页面传输大小
Requests per second: 10448.23 [#/sec] (mean) #每秒多少请求/s(总请求数/总共完成的时间)
Time per request: 0.191 [ms] (mean) #客户端访问服务端, 单个请求所需花费的时间
Time per request: 0.096 [ms] (mean, across all concurrent requests) #服务端处理请求的时间
Transfer rate: 3091.61 [Kbytes/sec] received #判断网络传输速率, 观察网络是否存在瓶颈
二、了解影响性能指标
1.网络
网络的流量
网络是否丢包
这些会影响http的请求与调用
2.系统
硬件有没有磁盘损坏,磁盘速率
系统负载、内存、系统稳定性
3.服务
连接优化、请求优化
根据业务形态做对应的服务设置
4.程序
接口性能
处理速度
程序执行效率
5.数据库
每个架构服务与服务之间都或多或少有一些关联, 我们需要将整个架构进行分层, 找到对应系统或服务的短板, 然后进行优化
三、系统性能优化
文件句柄, Linux一切皆文件,文件句柄可以理解为就是一个索引
文件句柄会随着我们进程的调用频繁增加
系统默认对文件句柄有限制,不能让一个进程无限的调用
需要限制每个进程和每个服务使用多大的文件句柄
文件句柄是必须要调整的优化参数
设置方式
系统全局性修改
用户局部性修改
进程局部性修改
[root@nginx ~]# vim /etc/security/limits.conf
#针对root用户,soft提醒,hard限制,nofile打开最大文件数
root soft nofile 65535
root hard nofile 65535
# *代表所有用户
* soft nofile 25535
* hard nofile 25535
#对于Nginx进程
worker_rlimit_nofile 65535;
四、静态资源优化
1. Nginx版本隐藏优化
#参数语法
Syntax: server_tokens on | off ;
Default: server_tokens on;
Context: http, server, location
#配置实例
server {
listen 80;
server_name test.qls.com;
server_tokens off;
root /code/test;
location / {
index index.php index.html;
}
}
#没有配置之前测试
[root@db01 ~]# curl -I 10.0.0.7
HTTP/1.1 200 OK
Server: nginx/1.16.1
Date: Thu, 12 Dec 2019 12:19:01 GMT
Content-Type: text/html
Content-Length: 5
Last-Modified: Thu, 12 Dec 2019 12:18:36 GMT
Connection: keep-alive
ETag: "5df2301c-5"
Accept-Ranges: bytes
#配置优化参数后测试
[root@db01 ~]# curl -I 10.0.0.7
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 12 Dec 2019 12:20:36 GMT
Content-Type: text/html
Content-Length: 5
Last-Modified: Thu, 12 Dec 2019 12:18:36 GMT
Connection: keep-alive
ETag: "5df2301c-5"
Accept-Ranges: bytes
2. CPU亲和与Worker进程
CPU亲和(affinity)减少进程之间不断频繁切换,减少性能损耗,其实现原理是将CPU核心和Nginx工作进程绑定方式,把每个worker进程固定对应的cpu上执行,减少切换cpu的cache miss,获得更好的性能。
1.查看当前CPU物理状态
[root@qiudao ~]# lscpu |grep "CPU(s)"
CPU(s): 2
On-line CPU(s) list: 0,1
NUMA node0 CPU(s): 0,1
2.将Nginx worker进程绑至不同的核心上,官方建议与cpu的核心保持一致
# 第一种绑定组合方式
worker_processes 24;
worker_cpu_affinity 000000000001 000000000010 000000000100 000000001000 000000010000 000000100000 000001000000 000010000000 000100000000 001000000000 010000000000 10000000000;
# 第二种方式
worker_processes 2;
worker_cpu_affinity 101010101010 010101010101;
# 最佳方式绑定方式
worker_processes auto;
worker_cpu_affinity auto;
#配置实例
[root@qiudao ~]# vim /etc/nginx/nginx.conf
user www;
worker_processes auto;
worker_cpu_affinity auto;
#配置之前测试
[root@qiudao ~]# ps aux |grep nginx
root 15705 0.0 0.0 46568 1256 ? Ss Nov26 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
www 15706 0.0 0.4 50908 7640 ? S Nov26 0:57 nginx: worker process
#配置之后测试
[root@qiudao ~]# ps aux |grep nginx
root 15705 0.0 0.1 47368 2968 ? Ss Nov26 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
www 27932 0.0 0.1 47372 2192 ? S 20:56 0:00 nginx: worker process
www 27933 0.0 0.1 47372 2192 ? S 20:56 0:00 nginx: worker process
3. 上传文件大小的限制
#语法说明
syntax:client_max_body_size size; #<==参数语法
default:client_max_body_size 1m; #<==默认值是1m
context:http,server,location #<==可以放置的标签段
#实例配置
http {
sendfile on;
keepalive_timeout 65;
client_max_body_size 8m; # 设置上传文件最大值8M
}
4. URL访问控制
1.根据目录或扩展名,禁止用户访问指定数据信息
location ~ ^/images/.*.(php|php5|sh|pl|py|html)$
{
deny all;
}
location ~ ^/static/.*.(php|php5|sh|pl|py)$
{
deny all;
}
location ~* ^/data/(attachment|avatar)/.*.(php|php5)$
{
deny all;
}
2.当访问禁止的数据信息时,进行页面跳转
# Nginx下配置禁止访问*.txt和*.doc文件。
location ~* .(txt|doc)$ {
if (-f $request_filename){
root /data/www/www;
#rewrite …..可以重定向到某个URL
break;
}
}
location ~* .(txt|doc)${
root /data/www/www;
denyall;
}
3.根据IP地址或网络进行访问策略控制
location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
deny all;
}
4.采用if判断方式,进行访问控制
if ($remote_addr = 10.0.0.7){
return 403;
}
5. 禁止非法域名解析访问网站
第一种方式:配置一个server虚拟主机区块,放置在所有server区块最前面
server {
listen 80;
server_name _;
return 501;
}
第二种方式:将计就计,通过你的域名访问时候,自动跳转到我的域名上
server {
listen 80 default_server;
server_name _;
rewrite ^(.*) http://www.qls.com/$1 permanent;
}
if ($host !~ ^www.nmtui.com$)
{
rewrite ^(.*) http://www.qls.com/$1 permanent;
}
6. 防盗链解决方案
什么是资源盗链 ?
简单地说,就是某些不法网站未经许可,通过在其自身网站程序里非法调用其他网站的资源,然后在自己的网站上显示这些调用的资源,达到填充自身网站的效果。
Syntax: valid_referers none | blocked | server_names | string ...;
Default: —
Context: server, location
1.准备html文件
[root@web01 /code/test]# cat daolian.html
<html>
<head>老男孩教育
<title>
</title>
</head>
<body bgcolor=green>
欢迎访问!
<br>
<a href="http://test.qls.com" target="_blank">博客地址
</a>
<img src="http://test.qls.com/test.jpg">
</body>
</html>
2.启动防盗链
#支持IP、域名、正则方式
location ~ .*.(jpg|gif|png)$ {
valid_referers none blocked www.xuliangwei.com;
if ($invalid_referer) {
return 403;
}
root /code/test;
}
3.验证
#伪造协议头访问
[root@db01 ~]# curl -e "http://www.baidu.com" -I http://10.0.0.7/test.jpg
HTTP/1.1 403 Forbidden
Server: nginx/1.16.1
Date: Thu, 12 Dec 2019 14:17:37 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive
#伪造协议头访问
[root@db01 ~]# curl -e "http://test.qls.com" -I http://10.0.0.7/test.jpg
HTTP/1.1 200 OK
Server: nginx/1.16.1
Date: Thu, 12 Dec 2019 14:18:14 GMT
Content-Type: image/jpeg
Content-Length: 24893
Last-Modified: Thu, 12 Dec 2019 14:14:12 GMT
Connection: keep-alive
ETag: "5df24b34-613d"
Accept-Ranges: bytes
7. 错误页面友好显示
范例1:对错误代码403实行本地页面跳转,命令如下:
error_page 403 /403.html; #当出现403错误时,会跳转到403.html页面
范例2:50x页面放到本地单独目录下,进行优雅显示。
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /www/html;
}
范例3:改变状态码为新的状态码,并显示指定的文件内容,命令如下:
error_page 404 =200 /index.html;
范例4:错误状态码URL重定向,命令如下:
error_page 404 https://www.increase93.com;
8. Nginx防爬虫优化
范例1:阻止下载协议代理,命令如下:
if ($http_user_agent ~* LWP::Simple|BBBike|wget)
{
return 403;
}
范例2:添加内容防止N多爬虫代理访问网站,命令如下:
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Yahoo!Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot")
{
return 403;
}
9. 限制HTTP的请求方法
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 501;
}
10. 优化nginx事件处理模型
use epoll; #指定使用的模型为epoll
11. 单个进程允许最大连接数
worker_connections 10240; #此数值设置不要超过系统最大打开文件数量
12. Worker进程最大打开数
worker_rlimit_nofile 20480; #设置worker进程打开文件数
13. 高效文件传输模式
syntax:sendfile on | off; #<==参数语法
default:sendfile off; #<==参数默认大小
context:http,server,location,if in location #<==可以放置的标签段
第一种方式:tcp_nopush
syntax: tcp_nopush on | off; #<==参数语法
default: tcp_nopush off; #<==参数默认大小
context: http,server,location #<==可以放置的标签段
#说明:将数据包积攒到一定量时再进行传输
第二种方式:tcp_nodelay
syntax: tcp_nodelay on | off;
Default: tcp_nodelay on;
Context: http, server, location
#说明:只要有数据包产生,不管大小多少,就尽快传输
#强调:两个指令是相悖的,请选择其一开启,不要同时开启;
#默认采用tcp_nodelay方式进行传输。
14. 设置Nginx服务超时参数
1.设置参数: keepalive_timeout 60; # 长连接才有意义
syntax:keepalive_timeout timeout [header_timeout]; #<==参数语法
default:keepalive_timeout 75s; #<==参数默认大小
context:http,server,location #<==可以放置的标签段
#说明:客户端和服务端都没有数据传输时,进行超时时间倒计时,一旦超时时间读取完毕还没有数据传输,就断开连接
2.设置参数:client_header_timeout 55;
syntax:client_header_timeout time; #<==参数语法
default:client_header_timeout 60s; #<==参数默认大小
context:http,server #<==可以放置的标签段
#说明:表示定义客户端请求报文发送的间隔超时时间,客户端发送的请求报文中请求头信息的间隔时间
3.设置参数:client_body_timeout 55;
syntax:client_body_timeout time; #<==参数语法
default:client_body_timeout 60s; #<==默认值是60秒
context:http,server,location #<==可以放置的标签段
#说明:表示定义服务端响应报文发送的间隔超时时间,客户端发送的请求报文中请求主体信息的间隔时间
4.设置参数:send_timeout 60s
syntax:send_timeout time; #<==参数语法
default:send_timeout 60s; #<==默认值是60秒
context:http,server,location #<==可以放置的标签段
#说明:表示定义客户端读取服务端响应报文的间隔超时时间,服务端发送的响应报文间隔时间
15. Nginx gzip压缩
Nginx gzip压缩模块提供了压缩文件内容的功能,用户请求的内容在发送到用户客户端之前, Nginx服务器会根据一些具体的策略实施压缩,以节约网站出口带宽,同时加快数据传输效率,来提升用户访问体验。
优点:
提升网站用户体验:
发送给用户的内容小了,用户访问单位大小的页面就加快了,用户体验提升了,网站口碑就好了。
节约网站带宽成本:
数据是压缩传输的,因此节省了网站的带宽流量成本,不过压缩时会稍
微消耗一些CPU资源,这个一般可以忽略。
此功能既能提升用户体验,又能使公司少花钱,一举多得。对于几乎所有的Web服务来说,这是一个非常重要的功能,Apache服务也有此功能。
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 4;
gzip_types text/css text/xml application/javascript;
gzip_vary on;
#说明:将服务端响应的数据信息进行压缩,可以有效节省带宽,提高用户访问效率
需要和不需要压缩的对象:
1.纯文本内容压缩比很高,因此,纯文本的内容最好进行压缩,例如:html、js、css、xml、shtml等格式的文件。
2.被压缩的纯文本文件必须要大于1KB,由于压缩算法的特殊原因,极小的文件压缩后可能反而变大。
3.图片、视频(流媒体)等文件尽量不要压缩,因为这些文件大多都是经过压缩的。
4.如果再压缩很可能不会减小或减小很少,或者有可能增大,同时压缩时还会消耗大量的CPU、内存资源。
压缩配置参数说明:
gzip on ;
#开启gzip压缩功能。
gzip_min_length lk;
#设置允许压缩的页面最小宇节数,页面宇节数从header头的Content-Length中获取。默认值是0,表示不管页面多大都进行压缩。建议设置成大于1K,如果小于1K可能会越压越大。
gzip_buffers 4 16k;
#压缩缓冲区大小。表示申请4个单位为16K的内存作为压缩结果流缓存,默认值是申请与原始数据
大小相同的内存空间来存储gzip压缩结果。
gzip_http_version 1.1;
#压缩版本(默认1.1,前端为squid2.5时使用1.0),用于设置识别HTTP协议版本,默认是1.1, 目前大部分浏览器已经支持GZIP解压,使用默认即可。
gzip_comp_level 2;
#压缩比率。用来指定gzip压缩比,1压缩比最小,处理速度最快;9压缩比最大,传输速度快,但处理最慢,也比较消耗CPU资源。
gzip_types text/plain application/x-javascript text/css application/xml;
#用来指定压缩的类型,"text/html"类型总是会被压缩,这个就是HTTP原理部分讲的媒体类型。
gzip_vary on;
#vary header支持。该选项可以让前端的缓存服务器缓存经过gzip压缩的页面,例如用Squid缓存
经过Nginx压缩的数据。
16. Nginx expires缓存
简单地说,Nginx expires的功能就是为用户访问的网站内容设定一个过期时间,当用户第一次访问这些内容时,会把这些内容存储在用户浏览器本地,这样用户第二次及以后继续访问该网站时,浏览器会检查加载已经缓存在用户浏览器本地的内容,就不会去服务器下载了,直到缓存的内容过期或被清除为止。
Nginx expires功能优点:
1.expires可以降低网站的带宽,节约成本。
2.加快用户访问网站的速度,提升用户访问体验。
3.服务器访问量降低了,服务器压力就减轻了,服务器成本也会降低,甚至可以节约人力成本。
4.对于几乎所有的Web服务来说,这是非常重要的功能之一,Apache服务也有此功能。
实践配置:
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 10y;
root html/blog;
}
location ~ .*.(js|css)$
{
expires 30d;
root html/blog;
}
location / {
expires 3650d;
}
企业网站有可能不希望被缓存的内容:
1.广告图片,用于广告服务,都缓存了就不好控制展示了。
2.网站流量统计工具(JS代码),都缓存了流量统计就不准了。
3.更新很频繁的文件(google的logo),这个如果按天,缓存效果还是显著的。
17. 配置FastCGI优化
FastCGI常见参数的Nginx配置示例如下:
http {
fastcgi_connect_timeout 240;
fastcgi_send_timeout 240;
fastcgi_read_timeout 240;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
fastcgi_cache_path /data/ngx_fcgi_cache levels=2:2 keys_zone=ngx_fcgi_cache:512m inactive=1d max_size=40g;
server {
fastcgi_cache ngx_fcgi_cache;
fastcgi_cache_valid 200 302 1h;
fastcgi_cache_valid 301 1d;
fastcgi_cache_valid any 1m;
fastcgi_cache_min_uses 1;
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_cache_key http://$host$request_uri;
}
}
Nginx FastCGI相关参数 | 说明 |
---|---|
fastcgi connect timeout | 表示nginx服务器和后端FastCGI服务器连接的超时时间,默认值为60秒,这个参数值通常不要超过75秒,因为建立的连接越多,消耗的资源就越多 |
fastcgi send timeout | 设置nginx传输请求到FastCGI服务器的超时时间,这个超时时间不是整个请求的超时时间,而是两个成功请求的之间间隔时间为超时时间,如果这个时间内,FastCGI服务没有收到任何信息,连接将关闭 |
fastcgi read timeout | 设置nginx从FastCGI服务器读取响应信息的超时时间苯示连捿建立成功后, nginx等待后端服务器的响应时间,是nginx进入后端的排队之中的等候处理的时间,实际上是读取FastCGI响应成功信息的间隔时间, |
fastcgi buffer size | 这是Nginx FastCGI的缓冲区大小参数,设定用来读取从FastCGI服务器端收到的第一部分响应信息的缓冲区大小,这里的第一部分通常会包含一个小的响应头部s默认情况下,这个参数的大小等价于_个内存页。不是4k就是8k 根据相应系统平台来决定,也可以更小。 |
fastcgi_buffers | 设定用来读取从FastCGI服务器端收到的响应信息的缓冲区大小和缓冲区数是,默认值为fastcgibuffer 8 4k|8k;指定本地需要用多少和多大的缓冲区来缓冲FastCGI的应答请求,如果一个 PHP脚本产生的页面大小为256KB ,那么会为其分配4个64KB的缓冲区来缓存;如果页面大小大于256KB ,那么大于256KB的部分会缓存到fastcgitemp 指定的路径中,但是这并不是好方法,因为内存中的数据处理速度要快于硬盘。一般这个值应该为站点中PHP脚本产生的页面大小的中间值,如果站点大部分脚本所产生的页面大小为256KB ,那么可以把这个值设置为"16 16k" , "4 64k"等 |
fastcgi busy buffers_size | 用于设置系统很忙时可以使用的fastcgibuffers大小,言方推荐的大小为fastcgibuffers2 ;默认值为fastcgibusy*buffers_size 8k|16k |
fastcgi temp file write size | FastCGI临时文件的大小,可以设置为128~256KB ; 默认fastcgitempfilewritesize 8k|16k; |
fastcgi cache oldboy nginx | 表示开后FastCGI缓存并为其指定一个名称。开后缓存非常有用,可以有效降低CPU的负载,并且防止502错误的发生,但是开后缓存也可能引起其它问题,要根据具体情况来选择 |
fastcgi cache path | 实例:fastcgicachepath /data/nginx/cache levels = 2:2 keyszone = ngxfcgicache:512m inactive = ld maxsize=40g; fastcgicache缓存目录,可以设置目录前列层级,比如2:2会生成256*256 个子目录,keyszone是这个缓存空间的名字,cache是用多少内存(这样热门的内容,nginx会直接放入内存,提高访问速度)。inactive表示默认失效时间,maxsize表示最多用多少硬盘空间,雲要注意的是fastcgicache缓存是先写在fastcgitemppath在移到fastcgicachepath中去的,所以这个两个目录最好在同一个分区,从0.8.9之后可以在不同的分区,不过还是建议放在同_分区。 |
fastcgi cache valid | 示例:fastcgicachevalid 200 302 lh; 用来指定应答代码的缓存时间,实例中的值表示将200和302应答缓存1个小时; 示例:fastcgicachevalid 301 Id; 将301应答缓存1天; |
fastcgi cache min_uses | 示例:fastcgicachemin_uses 1; 设置清求几次之后晌应将被缓存,1表示一次即被缓存 |
**fastcgi cache use_stale ** | 示例:fastcgicacheusestale error timeout invalidheader http_500 定义在哪些情况下使用过期缓存 |
**fastcgi cache key ** | 示例:fastcgicachekey requestmethod://requestmethod://hostrequesturi;fastcgi.cache.keyhttp://requesturi;fastcgi.cache.keyhttp://host$requesturi;定义fastcgicache的key ,示例中以请求的URI作为缓存的key,nginx会取这个key的md5作为缓存文件,如果设置了缓存散列目录,nginx会从后往前取梠应的位数作为目录。注意一定要加作为cache key,否则如果先请求的为head 类型,后面的GET清求返回为空。 |
18. 字符集优化
charset utf-8; #统一使用utf-8字符集
19. 日志优化
# 定义日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 访问日志
access_log /var/log/nginx/access.log main;
# 错误日志
error_log /var/log/nginx/error.log warn;
#进行日志的切割
#使用logrotate日志切割服务,进行日志切割