web架构-Nginx十二之性能优化

web架构-Nginx12之性能优化

MarkdownHTML

12·Nginx性能优化实践

  • 12·Nginx性能优化实践
    • [性能优化概述](file:///F:/老男孩视频/nginx常见问题/Nginx性能优化.html#title-1)
    • [压力测试工具](file:///F:/老男孩视频/nginx常见问题/Nginx性能优化.html#title-2)
    • [系统性能优化](file:///F:/老男孩视频/nginx常见问题/Nginx性能优化.html#title-3)
    • [代理服务优化](file:///F:/老男孩视频/nginx常见问题/Nginx性能优化.html#title-4)
    • [静态资源优化](file:///F:/老男孩视频/nginx常见问题/Nginx性能优化.html#title-5)
    • [静态资源读取](file:///F:/老男孩视频/nginx常见问题/Nginx性能优化.html#title-6)
    • [静态资源压缩](file:///F:/老男孩视频/nginx常见问题/Nginx性能优化.html#title-7)
    • [防止资源盗链](file:///F:/老男孩视频/nginx常见问题/Nginx性能优化.html#title-8)
    • [模拟盗链实例](file:///F:/老男孩视频/nginx常见问题/Nginx性能优化.html#title-9)
    • [允许跨域访问](file:///F:/老男孩视频/nginx常见问题/Nginx性能优化.html#title-10)
    • [CPU亲和配置](file:///F:/老男孩视频/nginx常见问题/Nginx性能优化.html#p)
    • [通用优化配置](file:///F:/老男孩视频/nginx常见问题/Nginx性能优化.html#title-11)
    • [Nginx安全与优化总结](file:///F:/老男孩视频/nginx常见问题/Nginx性能优化.html#title-12)

性能优化概述


基于Nginx性能优化,那么在性能优化这一章,我们将分为如下几方面做介绍

1、首先我们需要了解性能优化要考虑哪些方面。
2、然后我们需要了解性能优化必要用到的压力测试工具ab
3、最后我们需要了解系统上有哪些注意和优化的点,以及nginx配置文件

我们再做性能优化工作前,我们重点需要考虑哪些方面,和了解哪些方面

1、首先需要了解我们当前系统的结构和瓶颈,了解当前使用的是什么,运行的是什么业务,都有哪些服务,了解每个服务最大能支撑多少并发。比如nginx作为静态资源服务并发是多少,最高瓶颈在哪里,能支持多少qps(每秒查询率)的访问请求,那我们怎么得出这组系统结构瓶颈呢,比如top查看系统的CPU负载、内存使用率、总的运行进程等,也可以通过日志去分析请求的情况,当然也可以通过我们前面介绍到的stub_statius模块查看当前的连接情况,也可以对线上的业务进行压力测试(低峰期),去了解当前这套系统能承担多少的请求和并发,已做好响应的评估。这个是我们做性能优化最先考虑的地方。

2、其次我们需要了解业务模式,虽然我们是做性能优化,但每一个性能的优化都是为业务所提供的服务的,我们需要了解每个业务接口的类型,比如:电商网站中的抢购模式,这种情况下面,平时没什么流量,但到了抢购时间流量会突增。
我们还需要了解系统层次化的结构,比如:我们使用nginx做的是代理、还是动静分离、还是后端直接服务用户,那么这个就需要我们对每一层做好相应的梳理。以便更好的服务业务。

3、最后我们需要考虑性能与安全,往往注重了性能,但是忽略了安全。往往过于注重安全,对性能又会产生影响。比如:我们在设计防火墙功能时,检测过于严密,这样就会给性能带来影响。那么如果对于性能完全追求,却不顾服务的安全,这个也会造成很大的隐患,所以需要评估好两者的关系,把握好两者的孰重孰轻。以及整体的相关性,权衡好对应的点。

从OSI模型考虑优化方向

硬件 代理(CPU) 静态(磁盘IO) 动态(cpu、内存)
网络 带宽、丢包、延迟
系统 文件描述符(文件句柄数)
应用 服务与服务保持长连接 http1.1
服务 静态资源服务优化

压力测试工具

在系统业务量没有增长之前,我们就要做好相应的准备工作,以防患业务量突增带来的接口压力,所以对于接口压力测试就显得非常重要了,我们首先要评估好系统压力,然后使用工具检测当前系统情况,是否能满足对应压力的需求。


1.安装ab压力测试工具
[root@web01 conf.d]# yum install httpd-tools -y

2.压测工具使用方式
[root@web01 ~]# ab -n 200 -c 2 http://127.0.0.1/

#-n 要执行的请求数
#-c 请求的并发数
#-k 是否开启长连接

[root@web01 conf.d]# ab
ab: wrong number of arguments
Usage: ab [options] [http[s]://]hostname[:port]/path

3.配置Nginx静态网站与tomcat动态网站环境
#配置nginx
[root@web01 ~]#  vim /etc/nginx/conf.d/try.conf
server {
    listen 80;
    server_name try.oldboy.com;

    location / {
    root /code;
        try_files $uri $uri/ @java;
    index index.jsp index.html;
    }

    location @java {
    proxy_pass http://172.16.1.8:8080;
    }
}
#配置nginx使用的静态页面
echo "nginx ab" > /code/ab.html
#配置tomcat使用的静态页面
[root@web02 ~]# cd /usr/share/tomcat/webapps/ROOT
#压测工具测试nginx处理静态资源
[root@web01 ~]# ab -n 10000 -c 200 http://www.old.com/index.html
Server Software:        nginx/1.18.0
Server Hostname:        www.old.com
Server Port:            80

Document Path:          /index.html
Document Length:        32 bytes

Concurrency Level:      200
Time taken for tests:   0.838 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      1740000 bytes
HTML transferred:       320000 bytes
Requests per second:    11935.78 [#/sec] (mean)
Time per request:       16.756 [ms] (mean)
Time per request:       0.084 [ms] (mean, across all concurrent requests)
Transfer rate:          2028.15 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    3   1.2      2      10
Processing:     1    7   5.9      7     215
Waiting:        0    5   5.8      5     212
Total:          3   10   5.9      9     216

Percentage of the requests served within a certain time (ms)
  50%      9
  66%     10
  75%     11
  80%     11
  90%     12
  95%     13
  98%     16
  99%     17
 100%    216 (longest request)
[root@web01 conf.d]# ab -n 10000 -c 200 http://try.old.com/index.html
Server Software:        nginx/1.14.2
Server Hostname:        try.oldboy.com
Server Port:            80

Document Path:          /ab.html
Document Length:        9 bytes

Concurrency Level:      200
Time taken for tests:   1.078 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      2380000 bytes
HTML transferred:       90000 bytes
Requests per second:    9272.58 [#/sec] (mean)
Time per request:       21.569 [ms] (mean)
Time per request:       0.108 [ms] (mean, across all concurrent requests)
Transfer rate:          2155.15 [Kbytes/sec] received

#压测工具测试tomcat处理静态资源
[root@web01 ~]# ab -n 10000 -c 200 http://try.oldboy.com/index.html

Server Software:        nginx/1.18.0
Server Hostname:        try.oldboy.com
Server Port:            80

Document Path:          /index.html
Document Length:        7 bytes

Concurrency Level:      200
Time taken for tests:   1.033 seconds    #总花费总时长
Complete requests:      10000           #总请求数
Failed requests:        0              #请求失败数
Write errors:           0
Total transferred:      2360000 bytes    #总传输大小   
HTML transferred:       70000 bytes       #页面传输大小
Requests per second:    9680.08 [#/sec] (mean) #每秒多少请求/s(总请求数/总共完成的时间)
Time per request:       20.661 [ms] (mean) #客户端访问服务端, 单个请求所需花费的时间
Time per request:       0.103 [ms] (mean, across all concurrent requests)#服务端处理请求的时间
Transfer rate:          2230.96 [Kbytes/sec] received  #判断网络传输速率, 观察网络是否存在瓶颈
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    2   1.0      2       7
Processing:     6   10   7.6      9     405
Waiting:        1    8   7.6      7     402
Total:          6   13   7.6     12     406

Percentage of the requests served within a certain time (ms)
  50%     12
  66%     13
  75%     13
  80%     13
  90%     15
  95%     17
  98%     25
  99%     31
 100%    406 (longest request)

image-20200926174457871

4.了解影响性能指标
1、网络
    (1)网络的流量
    (2)网络是否丢包
    (3)这些会影响http的请求与调用
2、系统
    (1)硬件有没有磁盘损坏,磁盘速率
    (2)系统的负载、内存、系统稳定性
3、服务
    (1)连接优化。请求优化
    (2)根据业务形态做对应的服务设置
4、程序
    (1)接口性能
    (2)处理速度
    (3)程序执行效率
5、数据库
#每个服务与服务之间都或多或少有一些关联,我们需要将整个架构进行分层,找到对应系统或服务的短板,然后进行优化

系统性能优化

文件句柄,Linux一切皆文件,文件句柄可以理解为就是一个索引,文件句柄会随着我们进程的调用频繁增加,系统默认文件句柄是有限制的,不能让一个进程无限的调用,所以我们需要限制每个 进程和每个服务使用多大的文件句柄,文件句柄也是必须要调整的优化参数。

文件句柄的设置方式:
1、系统全局性修改。
2、用户局部性修改。
3、进程局部性修改。

[root@web01~]# vim /etc/security/limits.conf
[root@web01~]# 
1、系统全局性修改。
# * 代表所有用户
* soft nofile 25535
* hard nofile 25535
2.用户局部性修改
#针对root用户,soft仅提醒,hard限制,nofile打开最大文件数
root soft nofile 65535
root hard nofile 65535
修改完成进行重启操作
[root@web01~]#reboot
3.进程局部性修改
#针对nginx进程,nginx自带配置
worker_rlimit_nofile 30000
4.调整内核参数:让time_wait状态重用(端口重用)[flag]
[root@web01 ~]# vim /etc/sysctl.conf
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps = 1
[root@web01 ~]#  sysctl -p    #可以查看我们添加的内核参数
[root@web01 ~]#  sysctl -a    #可以查看所有内核参数

在高并发短连接的TCP服务器上,当服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量socket处于TIME_WAIT状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上。 我来解释下这个场景。主动正常关闭TCP连接,都会出现TIMEWAIT。

为什么我们要关注这个高并发短连接呢?有两个方面需要注意:

1.高并发可以让服务器在短时间范围内同时占用大量端口,而端口有个0~65535的范围,并不是很多,刨除系统和其他服务要用的,剩下的就更少了。  
2.在这个场景中,短连接表示`业务处理+传输数据的时间远远小于TIMEWAIT超时的时间`的连接。
这里有个相对长短的概念,比如取一个web页面,1秒钟的http短连接处理完业务,在关闭连接之后,这个业务用过的端口会停留在TIMEWAIT状态几分钟,而这几分钟,其他HTTP请求来临的时候是无法占用此端口的(占着茅坑不拉翔)。单用这个业务计算服务器的利用率会发现,服务器干正经事的时间和端口(资源)被挂着无法被使用的时间的比例是  1:几百,服务器资源严重浪费。(说个题外话,从这个意义出发来考虑服务器性能调优的话,长连接业务的服务就不需要考虑TIMEWAIT状态。同时,假如你对服务器业务场景非常熟悉,你会发现,在实际业务场景中,一般长连接对应的业务的并发量并不会很高。

代理服务优化

通常nginx作为代理服务,负责转发用户的请求,那么在转发的过程中建议开启HTTP长连接,用于减少握手次数,降低服务器损耗。


1.长连接语法示例(应用层面优化)
Syntax: keepalive connection;
Default: -
Context: upstream

#该指令出现在1.1.4版中

2.配置nginx代理服务使用长连接方式
upstream http_backend {
    server 127.0.0.1:8080;
    keepalive 16;   #长连接
}
配置详情
[root@lb01 conf.d]# !cat
cat proxy_ssl.conf
upstream website {
    server 172.16.1.7:80;
    server 172.16.1.8:80;
keepalive 16; #长连接;
}

server {
    listen 443 ssl;
    server_name s.ssl.com;
    ssl_certificate ssl_key/server.crt;
    ssl_certificate_key ssl_key/server.key;
    location / {
        proxy_pass http://website;
        proxy_set_header Host $http_host;
    }
}

server {
    listen 80;
    server_name s.ssl.com;
    return 302 https://$server_name$request_uri;
}


server {
    ...
    location /http/ {
        proxy_pass http://http_backend;
        proxy_http_version 1.1;         #对于http协议应该指定为1.1
        proxy_set_header Connection ""; #清除“connection”头字段
       [root@lb01 nginx]# cat proxy_params

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;

proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
proxy_set_header Connection ""; #清除“connection”头字段 
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;  #平滑过渡
[root@lb01 conf.d]# cat www.conf
upstream web1 {
    server 172.16.1.7:80;
    server 172.16.1.8:80;
}
server {
    listen 80;
    server_name blog.oldboy.com;
 
    location / {
        proxy_pass http://web1;
        include proxy_params;
        proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
    }
}
server {
    listen 80;
    server_name zh.oldboy.com;
 
    location / {
        proxy_pass http://web1;
        include proxy_params;
    }
}     
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwared-For $proxy_add_x_forwarded_for;
        proxy_connect_timeout 30s;      # 代理连接web超时时间
        proxy_read_timeout 60s;         # 代理等待web响应超时时间
        proxy_send_timeout 60s;         # web回传数据至代理超时时间
        proxy_buffering on;             # 开启代理缓冲区,web回传数据至缓冲区,代理边收边传返回给客户端
        proxy_buffer_size 32k;          # 代理接收web响应的头信息的缓冲区大小
        proxy_buffers 4 128k;           # 缓冲代理接收单个长连接内包含的web响应的数量和大小
    ...
    }
}

3.对于fastcgi服务器,需要设置fastcgi_keep_conn以便保持长连接[flag]
upstream fastcgi_backend {
    server 127.0.0.1:9000;
    keepalive 8;
}

server {
    ...
    location /fastcgi/ {
        fastcgi_pass fastcgi_backend;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_keep_conn on;   
        fastcgi_connect_timeout 60s;
        include fastcgi_params;
        ...
    }
}

注意:

1.scgi和uwsgi协议没有保持连接的概念。

2.但无论是proxy、fastcgi、uwsgi协议都有cache缓存的功能,开启后可加速网站访问的效率。(取决硬件)


keepalive_requests设置通过一个keepalive连接提供的最大请求数,在发出最大请求数后,将关闭连接

Syntax: keepalive_requests number;
Default: keepalive_requests 100;
Context: upstream

#该指令出现在1.15.3版中

keepalive_timeout设置超时,再次期间与代理服务器的空闲keepalive连接将保持打开状态

Syntax: keepalive_timeout timeout;
Default: keepalive_timeout 60s;
Context: upstream

#该指令出现在1.15.3版中

静态资源优化

Nginx作为静态资源Web服务器,用于静态资源处理,传输非常的高效

graph LR 客户 --REQ: jpeg html flv--> Nginx --> id2((静态文件存储))

静态资源指的是非WEB服务器端运行处理而生成的文件


静态资源类型 种类
浏览器渲染 HTML、CSS、JS
图片文件 JPEG、GIF、PNG
视频文件 FLV、Mp4、AVI
其他文件 TXT、DOC、PDF、…

浏览器缓存

浏览器缓存设置用于提高网站性能,尤其是新闻网站,图片一旦发布,改动的可能是非常小的,所以我们希望能否用户访问一次后,图片缓存在用户的浏览器长时间缓存。 浏览器是有自己的缓存机制,他是基于HTTP协议缓存机制来实现的,在HTTP协议中有很多头信息,那么实现浏览器的缓存就需要依赖特殊的头信息来与服务器进行特殊的验证,如Expires(http/1.0);Cache-control(http/1.1)。

graph LR 浏览器无缓存 客户 --> id1((无缓存)) --> id3((请求web服务器)) --> id4((请求后端服务器处理)) id4((请求后端服务器处理)) --> id5((web服务器)) --> 浏览器
graph LR 浏览器无缓存 客户 --> id1((有缓存)) --> id3((校验过期)) --> 浏览器

浏览器缓存过期校验机制

st=>start: 浏览器请求
e=>end: 给浏览器

op0=>operation: 有缓存
op1=>operation: 向web服务器请求If-None-Match
op2=>operation: 向web服务器请求If-Modified-Since
op3=>operation: 从缓存读取
op4=>operation: 向web服务器请求
op5=>operation: 请求后端,缓存协商
op6=>operation: 服务器决策
op7=>operation: 资源
op8=>operation: 返回给

cond1=>condition: 是否过期?
cond2=>condition: 有无Etag
cond3=>condition: last-Modified
cond4=>condition: 200(yes) or 304(no)

st->op0->cond1
cond1(yes)->cond2
cond1(no,bottom)->op3
op3->op7->op8->e
cond2(yes)->op1->op6
op6->cond4
cond2(no,bottom)->cond3
cond3(yes)->op2(right)->op6->cond4
cond3(no,bottom)->op4->op5(bottom)
op5(bottom)->e
cond4(yes)->op5(bottom)->e
cond4(no)->e

说明:

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.如何配置静态资源缓存expires
#作用:添加Cache-Control Expires头
Syntax: expires [modified] time;
        epoch | max | off;
Default: expires off;
Context: http, server, location, if in location

2.配置静态资源

​ 简单地说,Nginx expires的功能就是为用户访问的网站内容设定一个过期时间,当用户第一次访问这些内容时,会把这些内容存储在用户浏览器本地,这样用户第二次及以后继续访问该网站时,浏览器会检查加载已经缓存在用户浏览器本地的内容,就不会去服务器下载了,直到缓存的内容过期或被清除为止。

Nginx expires功能优点:

1.expires可以降低网站的带宽,节约成本。

2.加快用户访问网站的速度,提升用户访问体验。

3.服务器访问量降低了,服务器压力就减轻了,服务器成本也会降低,甚至可以节约人力成本。

4.对于几乎所有的Web服务来说,这是非常重要的功能之一,Apache服务也有此功能

[root@web01~]#vim /etc/nginx/conf.d/static.conf
server {
    listen 80;
    server_name static.oldboy.com;

    location ~ .*\.(jpg|gif|png)$ {
        expires      7d;
    add_header Cache-Control no-store;
    add_header Pragma no-cache;
    }
    location ~ .*\.(js|css)$ {
        expires      30d;
    }
}

如果开发代码没有正式上线,希望静态文件不被缓存

#取消js、css、html等静态文件缓存
location ~ .*\.(js|css|html)$ {
    add_header Cache-Control no-store;
    add_header Pragma no-cache;
}

企业网站有可能不希望被缓存的内容

1.广告图片,用于广告服务,都缓存了就不好控制展示了。
2.网站流量统计工具(JS代码),都缓存了流量统计就不准了。
3.更新很频繁的文件(google的logo),这个如果按天,缓存效果还是显著的。

静态资源读取


文件读取高效sendfile,如下图

Syntax: sendfile on | off;
Default: sendfile off;
Context: http, server, location, if in location

传统读取文件方式 VS sendfile读取文件方式


将多个包一次发送,用于提升网络传输效率,大文件推荐打开,需要开启sendfile才行

Syntax: tcp_nopush on | off;
Default: tcp_nopush off;
Context: http, server, location

提高网络传输实时性,需要开启keepalive,来一个包发一个包不等待行

Syntax: tcp_nodelay on | off;
Default: tcpnodelay off;
Context: http, server, location

静态资源压缩

1. 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;

#说明:将服务端响应的数据信息进行压缩,可以有效节省带宽,提高用户访问效率

2.需要和不需要压缩的对象:

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压缩的数据。

3.gzip传输压缩,传输前压缩,传输后解压

Syntax: gzip on | off;
Default: gzip off;
Context: http, server, location, if in location

4.gzip压缩哪些文件

Syntax: gzip_types mime-type ...;
Default: gzip_types text/html;
Context: http, server, location

5.gzip压缩比率,加快传输,但压缩本身比较耗费服务器性能

Syntax: gzip_comp_level level;
Default:gzip_comp_level level 1;
Context: http, server, location

6.gzip压缩协议版本,压缩使用在http哪个协议,主流选择1.1版本

Syntax: gzip_http_version 1.0 | 1.1;
Default:gzip_http_version 1.1;
Context: http, server, location

7.静态文件压缩案例

[root@web01 ~]# vim /etc/nginx/conf.d/static.conf
server {
    listen 80;
    server_name static.oldboy.com;

    location ~ .*\.(jpg|png|gif) {
        root /code/images;
        gzip on;
        gzip_types image/jpeg image/gif image/png;
        gzip_comp_level 2;
        gzip_http_version 1.1; 
    }
    location ~ .*\.(txt|xml|html|json|js|css)$ {
        #gzip on;
        #gzip_http_version 1.1;
       #gzip_comp_level 1;
        #gzip_types text/plain application/json application/x-javascript application/css application/xml text/javascript;
    #}
}

压缩txt文档
[root@web01 conf.d]# cp /etc/services /code/images/1.txt
[root@web01 conf.d]# ll -ah /code/images/1.txt
-rw-r--r-- 1 root root 655K Sep 27 17:13 /code/images/1.txt
[root@web01 conf.d]# cat /etc/services /etc/services  >> /code/images/1.txt
[root@web01 conf.d]# ll -lh /code/images/1.txt
-rw-r--r-- 1 root root 2.0M Sep 27 17:16 /code/images/1.txt



[root@web01 conf.d]#cat static.conf
server {
    listen 80;
    server_name static.oldboy.com;

   #location ~ .*\.(jpg|png|gif) {  (#注意同级别的location匹配不到需要注释)
        root /code/images;
        gzip on;
        gzip_types image/jpeg image/gif image/png;
        gzip_comp_level 2;
        gzip_http_version 1.1; 
    #}
    location ~ .*\.(txt|xml|html|json|js|css)$  (#不注释上面的location实际匹配到的是/code/index/1.txt)
    {
        gzip on;
        gzip_http_version 1.1;
       gzip_comp_level 1;
        gzip_types text/plain application/json application/x-javascript application/css application/xml text/javascript;
    }
}

image-20200927170855407

image-20200927173050948

8.配置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清求返回为空。

防止资源盗链

防盗链,指的是防止资源被其他网站恶意盗用。

基础防盗链设置思路:主要是针对客户端请求过程中所携带的一些Header信息来验证请求的合法性,比如客户端在请求的过程中都会携带referer信息。优点是规则简单,配置和使用都很方便,缺点是防盗链所依赖的Referer验证信息是可以伪造的,所以通过referer信息防盗链并非100%可靠,但是他能够限制大部分的盗链情况。

防盗链的实质:防盗链,就是不让别人盗用你网站上的资源,这个资源,通常指的是图片、视频、歌曲、文档等。
referer的概念
你通过A网站的一个页面http://a.com/a.html 里面的链接去访问B网站的一个页面http://b.com/b.html  ,那么这个B网站页面的referer就是http://a.com/a.html。 也就是说,一个referer其实就是一个网址。
Syntax: valid_referers none | blocked | server_name | string ...;
Default: -;
Context: server, location

#none: referer来源头部为空的情况
#blocked: referer来源头部不为空,这些都不以http://或者https://开头
#server_name: 来源头部信息包含当前域名,可以正则匹配

image-20200927175221845

1.配置防盗链

在盗链服务器上准备html文件,偷取我的图片

[root@web01 ~]# vim /code/index.html
<html>
<head>
    <meta charset="utf-8">
    <title>oldboy.com</title>
</head>
<body style="background-color:pink;">
    <center><img src="https://node.oldboy.com/daolian.jpg"/></center>
</body>
</html>

2.访问页面查看

image-20200927073640048


3.服务器上配置防盗链
location ~ .*\.(jpg|png|gif) {
         root /var/www/wordpress/wp-content/extra/;
         valid_referers none blocked *.oldboy.com;
         if ( $invalid_referer ) {
            return 403;
        }
}

返回403

image-20200927195948577

以上配置含义表示,所有来自*.oldboy.com都可以访问到当前站点的图片,如果来源域名不在这个列表中,那么$invalid_referer等于1,在if语句中返回一个403个客户,这样用户便会看到一个403的页面


5.如果不使用return而是用rewrite,那么盗链图片会返回一个pei.jpg给用户
#防盗链demo
location ~ .*\.(jpg|png|gif) {
            root /var/www/wordpress/wp-content/extra/;
            valid_referers none blocked *.oldboy.com;
            if ( $invalid_referer ) {
                rewrite ^(.*)$ /Picture/1.gif break;
            }
}

6.如果希望某些网站可以盗链
location ~ .*\.(jpg|png|gif) {
    root /data;
    valid_referers none blocked *.oldboy.com server_name ~\.google\. ~\.baidu\.;
    if ( $invalid_referer ) {
        return 403;
    }   
}

7.当然这种防护并不能百分百保证资源不被盗链,因为我们可以通过命令来修改来源的refer信息
#伪造协议头访问
[root@web01 code]# curl -e "https://test.node.com" -I http://node.oldboy.com/daolian.jpg
curl -e "https://test.oldboy.com" -I http://node.oldboy.com/daolian.jpg
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Sun, 27 Sep 2020 12:16:37 GMT
Content-Type: image/png
Content-Length: 67458
Last-Modified: Fri, 25 Sep 2020 07:43:19 GMT
Connection: keep-alive
ETag: "5f6d9f97-10782"
Accept-Ranges: bytes

#伪造协议头访问
[root@web01 code]# curl -e "https://test.oldboy.com" -I http://node.oldboy.com/daolian.jpg
curl -e "https://test.oldboy.com" -I http://node.oldboy.com/daolian.jpg
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Sun, 27 Sep 2020 12:16:37 GMT
Content-Type: image/png
Content-Length: 67458
Last-Modified: Fri, 25 Sep 2020 07:43:19 GMT
Connection: keep-alive
ETag: "5f6d9f97-10782"
Accept-Ranges: bytes

模拟盗链实例

1.配置被盗链机器
10.0.0.8 node.oldboy.com
#1.配置Nginx
[root@web01 conf.d]# cat node.conf 
server {
    listen 80;
    server_name node.oldboy.com;
    root /code;
    location / {
        index index.html;
    }
}

#2.上传2张图片
    一张是可以被盗链的图片
    一张是广告位的图片

#3.重启服务器
[root@web02 code]# systemctl restart nginx

2.另一台机器盗链
10.0.0.7  static.oldboy.com  ###盗链服务器
#1.配置Nginx
[root@web01 conf.d]# cat > /etc/nginx/conf.d/static.conf << EOF
server {
    server_name static.oldboy.com;
    listen 80;
    root /code;
    location / {
        index index.html;
    }
}
EOF

#2.配置盗链的页面
[root@web01 ~]# cd /code
[root@web01 code]# vim index.html
cat /code/index.html
<html>
<head>
    <meta charset="utf-8">
    <title>oldboy.com</title>
</head>
<body style="background-color:pink;">
    <center><img src="http://node.oldboy.com/daolian.jpg"/></center>
</body>
</html>

3.添加防盗链
location ~* \.(gif|jpg|png|bmp)$ {
    valid_referers none blocked *.oldboy.com;
    if ($invalid_referer) {
        return 403;                         #可以选择直接返回403
        rewrite ^(.*)$ /daolian.png break;      #也可以选择返回一张水印的图片,给公司做广告
}
root@web02 code]#cat /etc/nginx/conf.d/node.conf
server {
    listen 80;
    server_name node.oldboy.com;
    #location / {
        root /node;
        index index.html;
    #}
location ~ .*\.(jpg|png|gif) {
         #root /node;
         valid_referers none blocked *.node.com;
         if ( $invalid_referer ) {
   #return 403;  
rewrite ^(.*)$ /Picture/1.png break;

}
}
}  

image-20200927200714610

4. 错误页面友好显示
范例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;

5.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;
}

6.限制HTTP的请求方法

if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 501;
}

7.优化nginx事件处理模型

use epoll; #指定使用的模型为epoll

8.单个进程允许最大连接数

worker_connections 10240;    #此数值设置不要超过系统最大打开文件数量

9.Worker进程最大打开数

worker_rlimit_nofile 20480; #设置worker进程打开文件数

10. 高效文件传输模式

syntax:sendfile on | off; #<==参数语法
default:sendfile off; #<==参数默认大小
context:http,server,location,if in location #<==可以放置的标签段
10.1第一种方式:tcp_nopush
syntax: tcp_nopush on | off;     #<==参数语法
default: tcp_nopush off;     #<==参数默认大小
context: http,server,location #<==可以放置的标签段

#说明:将数据包积攒到一定量时再进行传输
10.2第二种方式:tcp_nodelay
syntax: tcp_nodelay on | off;
Default: tcp_nodelay on;
Context: http, server, location

#说明:只要有数据包产生,不管大小多少,就尽快传输
#强调:两个指令是相悖的,请选择其一开启,不要同时开启;
#默认采用tcp_nodelay方式进行传输。

11 设置Nginx服务超时参数

11.1 设置参数:keepalive_timeout 60; # 长连接才有意义
syntax:keepalive_timeout timeout [header_timeout];    #<==参数语法
default:keepalive_timeout 75s;                       #<==参数默认大小
context:http,server,location      #<==可以放置的标签段

#说明:客户端和服务端都没有数据传输时,进行超时时间倒计时,一旦超时时间读取完毕还没有数据传输,就断开连接
11.2 设置参数:client_header_timeout 55;
syntax:client_header_timeout time; 		#<==参数语法
default:client_header_timeout 60s; 		#<==参数默认大小
context:http,server 		#<==可以放置的标签段

#说明:表示定义客户端请求报文发送的间隔超时时间,客户端发送的请求报文中请求头信息的间隔时间
11.3 设置参数:client_body_timeout 55;
syntax:client_body_timeout time; 		#<==参数语法
default:client_body_timeout 60s; 		#<==默认值是60秒
context:http,server,location 		#<==可以放置的标签段

#说明:表示定义服务端响应报文发送的间隔超时时间,客户端发送的请求报文中请求主体信息的间隔时间
11.4 设置参数:send_timeout 60s;
syntax:send_timeout time; 		#<==参数语法
default:send_timeout 60s; 		#<==默认值是60秒
context:http,server,location 		#<==可以放置的标签段

#说明:表示定义客户端读取服务端响应报文的间隔超时时间,服务端发送的响应报文间隔时间

允许跨域访问

什么是跨域访问,当我们通过浏览器访问a网站时,同时会利用到ajax或其他方式,同时也请求b网站,这样的话就出现了请求一个页面,使用了两个域名,这种方式对浏览器来说默认是禁止的。

image-20200927202343290

​ 跨域访问

那Nginx语序跨站访问与浏览器有什么关系呢,因为浏览器会读取Access-Control-Allow-Origin的头信息,如果服务端允许,则浏览器不会进行拦截。

Syntax: add_header name value [always];
Default: -;
Context: http, server, location, if in location

web01配置跨域访问及所需文件
[root@web01 ~]# cat > /etc/nginx/conf.d/k.conf << EOF
server {
    listen 80;
    server_name k.oldboy.com;

    location / {
        root /code;
        index index.html;
    }
}
EOF

[root@web01 ~]# vi /code/k.html
<html lang="en">
<head>
        <meta charset="UTF-8" />
        <title>测试ajax和跨域访问</title>
        <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
</head>
<script type="text/javascript">
$(document).ready(function(){
        $.ajax({
        type: "GET",
        url: "http://s.oldboy.com",
        success: function(data) {
                alert("sucess 成功了!!!");
        },
        error: function() {
                alert("fail!!,跨不过去啊,不让进去啊,只能...!");
        }
        });
});
</script>
        <body>
                <h1>跨域访问测试</h1>
        </body>
</html>
[root@web01 ~]# systemctl reload nginx


web02配置正常访问及所需文件

[root@web02 ~]# cat > /etc/nginx/conf.d/s.conf <<EOF
server {
    listen 80;
    server_name s.oldboy.com;
    root /code;
    index index.html;
    charset utf-8;
}
EOF
[root@web02 ~]# echo web02 > /code/index.html
[root@web02 ~]# systemctl reload nginx

windows配置:在C:\Windows\System32\drivers\etc\hosts文件中添加一行10.0.0.7 k.oldboy.com 和一行10.0.0.8 s.oldboy.com

2.在浏览器访问测试http://s.oldboy.com和http://k.oldboy.com/k.html

image-20200928083549501

image-20200928084011235


3.web02配置允许跨域访问
[root@web02 ~]#vim /etc/nginx/conf.d/s.conf
server {
        listen 80;
        server_name s.oldboy.com;
        root /code;
        index index.html;
        charset utf-8;

        location ~ .*\.(html|htm)$ {
            add_header Access-Control-Allow-Origin *;
            add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
        }
}

4.再次浏览器访问测试

image-20200928084401351

CPU亲和配置

CPU亲和(affinity)减少进程之间不断频繁切换,减少性能损耗,其实现原理是建CPU核心和Nginx工作进程绑定方式,把每个worker进程固定到对应的cpu上执行,减少切换CPU的cache miss,获得更好的性能。

image-20200927142505262


1.查看当前CPU物理状态

[root@tomcat01 ~]$ lscpu | grep "CPU(s)"
CPU(s):                8
On-line CPU(s) list:   0-7
NUMA node0 CPU(s):     0-7

#以上服务器有一颗物理CPU,上面有8个核心

2.将nginx worker进程绑定至不通的核心上,官方建议与CPU的核心保持一致

# 第一种绑定组合方式(不推荐)
worker_processes 12;
worker_cpu_affinity 000000000001 000000000010 000000000100 000000001000 000000010000 000000100000 000001000000 000010000000 000100000000 001000000000 010000000000 10000000000;

# 第二种方式(使用较少)
worker_processes 2;
worker_cpu_affinity 101010101010 010101010101;

# 第三种最佳绑定方式,修改nginx启动的work进程为自动。
worker_processes  auto;
worker_cpu_affinity auto;

3.查看nginx worker进程绑定至对应cpu

[root@web01 ~]# ps -eo pid,args,psr|grep [n]ginx
  1242 nginx: master process /usr/   2
  1243 nginx: worker process         0
  1244 nginx: worker process         1
  1245 nginx: worker process         2
  1246 nginx: worker process         3

4.上传文件大小的限制

#语法说明
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访问控制

4.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;
} 
4.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;
}
4.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;
}

通用优化配置

1.nginx优化总结,nginx通用优化配置文件
[root@web01 ~]# vim /etc/nginx/nginx.conf
user www;                   # nginx进程启动用户
worker_processes auto;      #与cpu核心一致即可
worker_cpu_affinity auto;   # cpu亲和

error_log /var/log/nginx/error.log warn;    # 错误日志
pid /run/nginx.pid;
worker_rlimit_nofile 35535;     #每个work能打开的文件描述符,调整至1w以上,负荷较高建议2-3w

events {
    use epoll;                  # 使用epoll高效网络模型
    worker_connections 10240;   # 限制每个进程能处理多少个连接,10240x[cpu核心]
}

http {
    include             mime.types;
    default_type        application/octet-stream;
    charset utf-8;      # 统一使用utf-8字符集

    # 定义日志格式
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    #定义json日志格式              
    log_format json_access '{"@timestamp":"$time_iso8601",'
                      '"host":"$server_addr",'
                      '"clientip":"$remote_addr",'
                      '"size":$body_bytes_sent,'
                      '"responsetime":$request_time,'
                      '"upstreamtime":"$upstream_response_time",'
                      '"upstreamhost":"$upstream_addr",'
                      '"http_host":"$host",'
                      '"url":"$uri",'
                      '"domain":"$host",'
                      '"xff":"$http_x_forwarded_for",'
                      '"referer":"$http_referer",'
                      '"status":"$status"}';

    access_log  /var/log/nginx/access.log  main;    # 访问日志

    server_tokens off;  # 禁止浏览器显示nginx版本号
    client_max_body_size 200m;  # 文件上传大小限制调整

    # 文件高效传输,静态资源服务器建议打开
    sendfile            on;
    tcp_nopush          on;
    # 文件实时传输,动态资源服务建议打开,需要打开keepalive
    tcp_nodelay         on;
    keepalive_timeout   65;

    # Gzip 压缩
    gzip on;
    gzip_disable "MSIE [1-6]\.";    #针对IE浏览器不进行压缩
    gzip_http_version 1.1;
    gzip_comp_level 2;      #压缩级别
    gzip_buffers 16 8k;     #压缩的缓冲区
    gzip_min_length 1024;   #文件大于1024字节才进行压缩,默认值20
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript image/jpeg;

    # 虚拟主机
    include /etc/nginx/conf.d/*.conf;
}

2.字符集优化

charset utf-8; #统一使用utf-8字符集

3.日志优化

# 定义日志格式
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日志切割服务,进行日志切割  

4.Nginx安全与优化总结

1、CPU亲和、worker进程数、调整每个worker进程打开的文件数
2、使用额pool网络模型、调整每个worker进程的最大连接数
3、文件的高效读取sendfile、nopush
4、文件的传输实时性、nodealy
5、开启tcp长连接,以及长连接超时时间keepalived
6、开启文件传输压缩gzip
7、开启静态文件expires缓存
8、异常nginx版本号
9、禁止通过ip地址访问,禁止恶意域名解析,只允许域名访问
10、配置防盗链、以及跨域访问
11、防DDOS、cc攻击,限制单IP并发连接,以及http请求
12、优雅限制nginx错误页面
13、nginx加密传输https优化
14、nginx proxy_cache、fastcgi_cache、uwsgi_cache 缓存,第三方工具(squid、varnish)

PHP优化

1.配置PHP页面

[root@web02 ~]# vim /etc/nginx/conf.d/php.conf
server {
    listen 80;
    server_name linux.php.com;
    root /code/php;
    index index.php;

    location ~* \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

#配置站点
[root@web02 ~]# vim /code/php/index.php 
<?php
    phpinfo();

2.php.ini配置文件优化

#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#; Error handling and logging ;
#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
expose_php = Off                        # 关闭php版本信息
display_error = Off                     # 屏幕不显示错误日志(开发环境可以开启 on)
error_reporting = E_ALL                 # 记录PHP的每个错误
log_errors = On                         # 开启错误日志
error_log = /var/log/php_error.log      # 错误日志写入的位置(程序处理代码时的错误)
date.timezone = Asia/Shanghai           # 调整时区,默认PRC

#;;;;;;;;;;;;;;;;
#; File Uploads ;
#;;;;;;;;;;;;;;;;
file_uploads = On           # 允许文件上传
upload_max_filesize = 300M  # 允许上传文件的最大大小
post_max_size = 300M        # 允许客户端单个POST请求发送的最大数据
max_file_uploads = 20       # 允许同时上传的文件的最大数量
memory_limit = 128M         # 每个脚本执行最大内存

3.PHP危险函数

有时候为了安全我们需要禁掉一些PHP危险函数,整理如下需要的朋友可以参考下 
phpinfo() 
功能描述:输出 PHP 环境信息以及相关的模块、WEB 环境等信息。 
危险等级:中

passthru() 
功能描述:允许执行一个外部程序并回显输出,类似于 exec()。 
危险等级:高

exec() 
功能描述:允许执行一个外部程序(如 UNIX Shell 或 CMD 命令等)。 
危险等级:高

system() 
功能描述:允许执行一个外部程序并回显输出,类似于 passthru()。 
危险等级:高

chroot() 
功能描述:可改变当前 PHP 进程的工作根目录,仅当系统支持 CLI 模式 
PHP 时才能工作,且该函数不适用于 Windows 系统。 
危险等级:高

scandir() 
功能描述:列出指定路径中的文件和目录。 
危险等级:中

chgrp() 
功能描述:改变文件或目录所属的用户组。 
危险等级:高

chown() 
功能描述:改变文件或目录的所有者。 
危险等级:高

shell_exec() 
功能描述:通过 Shell 执行命令,并将执行结果作为字符串返回。 
危险等级:高

proc_open() 
功能描述:执行一个命令并打开文件指针用于读取以及写入。 
危险等级:高

proc_get_status() 
功能描述:获取使用 proc_open() 所打开进程的信息。 
危险等级:高

error_log() 
功能描述:将错误信息发送到指定位置(文件)。 
安全备注:在某些版本的 PHP 中,可使用 error_log() 绕过 PHP safe mode, 
执行任意命令。 
危险等级:低

ini_alter() 
功能描述:是 ini_set() 函数的一个别名函数,功能与 ini_set() 相同。 
具体参见 ini_set()。 
危险等级:高

ini_set() 
功能描述:可用于修改、设置 PHP 环境配置参数。 
危险等级:高

ini_restore() 
功能描述:可用于恢复 PHP 环境配置参数到其初始值。 
危险等级:高

dl() 
功能描述:在 PHP 进行运行过程当中(而非启动时)加载一个 PHP 外部模块。 
危险等级:高

pfsockopen() 
功能描述:建立一个 Internet 或 UNIX 域的 socket 持久连接。 
危险等级:高

syslog() 
功能描述:可调用 UNIX 系统的系统层 syslog() 函数。 
危险等级:中

readlink() 
功能描述:返回符号连接指向的目标文件内容。 
危险等级:中

symlink() 
功能描述:在 UNIX 系统中建立一个符号链接。 
危险等级:高

popen() 
功能描述:可通过 popen() 的参数传递一条命令,并对 popen() 所打开的文件进行执行。 
危险等级:高

stream_socket_server() 
功能描述:建立一个 Internet 或 UNIX 服务器连接。 
危险等级:中

putenv() 
功能描述:用于在 PHP 运行时改变系统字符集环境。在低于 5.2.6 版本的 PHP 中,可利用该函数 
修改系统字符集环境后,利用 sendmail 指令发送特殊参数执行系统 SHELL 命令。 
危险等级:高

禁用方法如下: 
打开/etc/php.ini文件, 
查找到 disable_functions ,添加需禁用的函数名,如下: 
phpinfo,eval,passthru,exec,system,chroot,scandir,chgrp,chown,
shell_exec,proc_open,proc_get_status,ini_alter,ini_alter,ini_restore,dl,p

4.php-fpm服务配置

1)php-fpm.conf配置优化
[root@web02 ~]# vim /etc/php-fpm.conf
[global]
;pid = /var/log/php-fpm/php-fpm.pid         # pid文件存放的位置
;error_log = /var/log/php-fpm/php-fpm.log   # 错误日志存放的位置(启动时的日志)
;log_level = error                  	    # 日志级别, alert, error, warning, notice, debug
rlimit_files = 65535                	    # php-fpm进程能打开的文件句柄数
;events.mechanism = epoll           	    # 使用epoll事件模型处理请求
include=/etc/php-fpm.d/*.conf
2)包含配置文件优化
[root@web02 ~]# vim /etc/php-fpm.d/www.conf
[www]       				          # 池名称
user = www  				          # 进程运行的用户
group = www 				          # 进程运行的组
;listen = /dev/shm/php-fpm.sock                   # 监听在本地socket文件
listen = 127.0.0.1:9000                           # 监听在本地tcp的9000端口
;listen.allowed_clients = 127.0.0.1               # 允许访问FastCGI进程的IP,any不限制 
pm = dynamic                                      # 管理方式(dynamic为动态,static为静态)
pm.max_children = 512                             # 最大启动的php-fpm进程数(静态管理,配置dynamic时失效)
pm.start_servers = 32                             # 动态方式下的起始php-fpm进程数量。
pm.min_spare_servers = 32                         # 动态方式下的最小php-fpm进程数量。
pm.max_spare_servers = 64                         # 动态方式下的最大php-fpm进程数量。
pm.max_requests = 1500                            # 达到这个请求数,子进程会重启,如果是0那就一直接受请求
pm.process_idle_timeout = 15s;                    # 没有请求时多久释放一个进程
pm.status_path = /phpfpm_status                   # 开启php的状态页面

php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/phpfpm_error.log
php_admin_flag[log_errors] = on
request_slowlog_timeout = 5s                      # php脚本执行超过5s的文件
slowlog = /var/log/php_slow.log                   # 记录至该文件中

5.php状态页

1)配置php

[root@web02 ~]# vim /etc/php-fpm.d/www.conf
pm.status_path = /phpfpm_status 		#开启php的状态页面

[root@web02 ~]# systemctl restart php-fpm

2)配置nginx

[root@web02 ~]# cat /etc/nginx/conf.d/php.conf
server {
	listen 80;
	server_name linux.php.com;
	root /code/php;
	index index.php;
	location ~* \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
	}
	location /status {
		stub_status;
	}
	location /php_status {
		fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
	}	
}

3)访问页面

#访问  http://linux.php.com/php_status
pool:                 www				# 池名称
process manager:      dynamic				# 动态管理
start time:           14/Sep/2020:18:52:12 +0800	# 启动时间
start since:          14				# 启动了多久
accepted conn:        1					# 连接数
listen queue:         0					# 等待队列
max listen queue:     0					# 最大等待队列
listen queue len:     511				# 等待队列长度
idle processes:       4					# 空闲的进程数
active processes:     1					# 活跃的进程数
total processes:      5					# 总的进程数
max active processes: 1					# 最大的活跃进程数
max children reached: 0					# 进程最大的限制连接数
slow requests:        0					# 慢查询

优化总结

1.nginx
	1)硬件	nginx做代理比较消耗CPU,如果做静态资源处理要考虑磁盘和IO
	2)网络
	3)系统
	4)应用	nginx做代理,开启长连接
	5)服务	nginx处理静态资源做缓存,做压缩,防盗链,跨域访问
	
2.php
	1)php.ini		    文件上传,访问日志
	2)php-fpm.conf		php状态页面,PHP慢查询

性能优化

nginx.conf

user  nginx;
worker_processes  4;
worker_cpu_affinity 0001 0010 0100 1000;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

worker_priority -20;
worker_rlimit_nofile 65535;
events {
    worker_connections  25535;
    accept_mutex on;
    multi_accept on;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    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;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

sysctl.conf

查看内核参数配置值:
[root@Server1 nginx]# sysctl -a
1、每个网络接口的处理速率比内核处理包的速度快的时候,允许发送队列的最大数目。
net.core.netdev_max_backlog = 1000  # 默认1000,建议:102400
2、调节系统同时发起的TCP连接数,默认值一般为128,在客户端存在高并发请求的时候,128就变得比较小了,可能会导致链接超时或者重传问题。
net.core.somaxconn = 128  # 默认128,高并发的情况时候要设置大一些,建议:102400
3、设置系统中做多允许多少TCP套接字不被关联到任何一个用户文件句柄上,如果超出这个值,没有与用户文件句柄关联的TCP套接字将立即被复位,同时给出警告信息,这个值是简单防止DDOS(Denial of service)的攻击,在内存比较充足的时候可以设置大一些:
net.ipv4.tcp_max_orphans = 32768 # 默认32768,建议:102400
4、记录尚未收到客户度确认消息的连接请求的最大值,一般要设置大一些:
net.ipv4.tcp_max_syn_backlog = 256  # 默认256,建议:102400
5、设置时间戳,可以避免序列号的卷绕,有时候会出现数据包用之前的序列号的情况,此值默认为1表示不允许序列号的数据包,对于Nginx服务器来说,要改为0禁用对于TCP时间戳的支持,这样TCP协议会让内核接受这种数据包,从而避免网络异常,如下:
net.ipv4.tcp_timestamps = 1 # 默认1,建议:0
6、设置内核放弃TCP连接之前向客户端发生SYN+ACK包的数量,网络连接建立需要三次握手,客户端首先向服务器发生一个连接请求,服务器收到后由内核回复一个SYN+ACK的报文,这个值不能设置过多,会影响服务器的性能,还会引起syn攻击:
net.ipv4.tcp_synack_retries = 5 # 默认为5,避免syn攻击,建议:1
7、与上一个功能类似,设置为1即可:
net.ipv4.tcp_syn_retries = 5 # 默认为5,避免syn攻击,建议:1

Nginx

优先顺序:location > server >http
posted @ 2021-03-07 22:55  上善若水~小辉  阅读(249)  评论(0编辑  收藏  举报