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,获得更好的性能。

Nginx优化总结-LMLPHP

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;
}
}
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 sizeFastCGI临时文件的大小,可以设置为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日志切割服务,进行日志切割
05-28 21:17