性能优化概述
基于Nginx性能优化,那么在性能优化这一章,我们将分为如下几个方面做介绍
我们在性能优化工作前,我们重点需要考虑哪些方面,和了解哪些方面
从OSI七层模型去考虑
硬件: 代理(cpu),静态(磁盘空间、IO),动态(cpu、内存)
网络: 网络是否有延迟,网卡是否有丢包
系统: 文件句柄(文件描述符)
应用: 服务与服务之间保持长连接 http1.1(开启长链接会占用端口,状态会变成TIME_WAIT) # netstat -an命令查看端口号状态
服务: Nginx静态资源服务优化
在系统业务量没有增长之前,我们就要做好相应的准备工作,已防患业务量徒增带来的接口压力,所以对于接口压力测试就显得非常重要了。我们首先要评估好系统压力,然后是由工具检查当前系统情况,是否能满足对压力的需求。
静态资源压力测试
- web01服务器
1. 修改Nginx配置文件
vim /etc/nginx/conf.d/try.conf
server {
listen 80;
server name _;
location / {
root /code;
try_files $uri @java; # $uri,输入192.168.15.7/tt.html,可以正常访问到数据 否则返回@java的数据
}
location @java {
proxy_pass http://127.0.0.1:8080; # 本地回环地址tomcat(端口号8080)
}
}
2. 创建Nginx配置文件指定的数据文件
echo "nginx ab" > /code/tt.html
3. 重启Nginx服务
systemctl restart nginx
1. 安装ab压力测试工具
yum install httpd-tools
2. ab命令使用格式及其常用的参数
ab -n10000 -c200 http://127.0.0.1/tt.html/
-n : 总的请求数
-c : 同时并发的请求数
-k : 开启长连接(http1.1)
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software: nginx/1.20.0 Nginx版本
Server Hostname: 127.0.0.1 主机
Server Port: 80 端口
Document Path: /tt.html/ 路径
Document Length: 157 bytes 字节
Concurrency Level: 200 并发数200
Time taken for tests: 1.999 seconds 请求的总时间
Complete requests: 10000 总请求
Failed requests: 0 失败的请求
Write errors: 0
Non-2xx responses: 10000
Total transferred: 3090000 bytes 所以请求总共占用的字节
HTML transferred: 1570000 bytes 传输的字节
Requests per second: 5001.76 [#/sec] (mean) qps每秒能处理多少请求(这个参数是重点!!!)
Time per request: 39.986 [ms] (mean) 客户端请求服务端的时间(毫秒)
Time per request: 0.200 [ms] (mean, across all concurrent requests) 服务端每个请求处理的时间(毫秒)
Transfer rate: 1509.32 [Kbytes/sec] received 传输的速率(网络问题)
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 10 82.9 3 1005
Processing: 5 23 9.9 19 225
Waiting: 1 20 10.5 16 224
Total: 5 33 83.0 23 1039
Percentage of the requests served within a certain time (ms)
50% 23
66% 31
75% 33
80% 34
90% 36
95% 38
98% 40
99% 42
100% 1039 (longest request)
动态资源压力测试
1. 下载tomcat软件包
wget https://mirrors.bfsu.edu.cn/apache/tomcat/tomcat-10/v10.0.6/bin/apache-tomcat-10.0.6.tar.gz
2. 解压tomcat软件包
tar -xf apache-tomcat-10.0.6.tar.gz
3. 创建tomcat动态资源
cd apache-tomcat-10.0.6/webapps/ROOT/
mv /code/tt.html ./
4. 启动tomcat程序
yum -y install java
cd /root/apache-tomcat-10.0.6/
./bin/startup.sh 启动tomcat服务
netstat -lntp 查看tomcat端口号
# tcp6 0 0 127.0.0.1:8005 :::* LISTEN 1890/java 关闭端口
# tcp6 0 0 :::8080 :::* LISTEN 1890/java 对外提供访问的端口
5. 进行ab压力测试
ab -n10000 -c200 http://127.0.0.1/tt.html/
Requests per second: 1033.30 [#/sec] (mean) qps每秒能处理多少请求(这个参数是重点!!!)
- 测试结果
我们很明显的可以感受到Nginx处理静态资源的速度明显比tomcat处理动态资源的速度要快很多
所以我们通常会用tomcat解析专门的jsp文件,Nginx通常会用来处理静态资源
了解影响性能指标
文件句柄,linux一切皆文件,文件句柄可以理解为就是一个索引,文件句柄会随着我们进程的调用频繁增加,系统默认文件句柄是有限制的,不能让一个进程无限的调用,所以我们需要限制每一个进程和每个服务使用多大的文件句柄,文件句柄也是必须要调整的优化参数。
文件句柄的设置方式,1.系统全局性修改。 2.用户局部性修改。 3.进程局部性修改。
- 系统层面必须要调整
查看系统设置的最大文件句柄
ulimit -n
# 65535
修改系统设置的文件句柄大小的配置文件
vim /etc/security/limits.conf
1. 系统全局性修改
# * -代表所有
* - nofile 65535
# *代表所有用户
* soft nofile 65536
* hard nofile 65536
2. 用户局部性修改
# 争对root用户,soft仅提醒,hard限制,nofile打开最大文件数
root soft nofile 65536
root hard nofile 65536
3. 进程局部性修改
vim /etc/nginx/nginx.conf
# 针对Nginx进程
worker_rlimit_nofile 65536;
使用lsof命令查看进程占用了多少个文件句柄
ps aux | grep nginx
# root 1718 0.0 0.0 46504 988 ? Ss 11:26 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
yum -y install lsof
lsof -p 1718 | wc -l # lsof -p 查看Nginx进程占用了多少个文件句柄
# 32
- 调整内核参数: 让time_wait状态重用(让占用的端口复用)
vim /etc/sysctl.conf
net.ipv4.tcp_tw_reuse = 1 # 让占用的端口复用
net.ipv4.tcp_timestamps = 1 # 时间戳
查看自定义设置的内核参数
sysctl -p
查看系统所有的内核参数
sysctl -a
通常Nginx作为代理服务,负责转发用户的请求,那么在转发的过程中建议开启HTTP长连接,用户减少握手的次数,降低服务器损耗。
1. 配置Nginx代理服务使用长连接方式keepalive connections(应用层面优化)
vim /etc/nginx/conf.d/proxy.conf
upstream test {
server 172.16.1.8:80;
keepalive 32; # 长连接
keepalived_requests 100; # 设置通过一个keepalive连接提供的最大请求数100。在发出最大请求数后,将关闭连接。
keepalive_timeout 60s; # 设置超时,webserver在处理完一个请求后保持这个TCP连接的打开状态。指定每个TCP连接最多可以保持多长时间。
}
server {
...
location /http/ {
proxy_pass http://http_backend;
proxy_http_version 1.1; # 对于http协议应该指定为1.1
proxy_set_header Connection ""; # 清除"connection"头字段 , Connection: keep-alive
proxy_set_header Host $http_host; # 代理服务器匹配请求web01服务器的时候,默认加上Host头信息(域名)
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 追加客户端ip地址以及全链路ip地址到web服务器记录日志
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
# 当Nginx虚拟服务池其中任意一台服务器返回错误码500,502,503,504等错误时,可以分配到下一台服务器程序继续处理,提高平台访问的成功率
proxy_connect_timeout 60s; # nginx代理与后端服务器连接超时时间(代理连接超时)
proxy_read_timeout 60s; # nginx代理等待后端服务器的响应时间(代理响应超时)
proxy_send_timeout 60s; # 后端服务器数据回传给nginx代理超时时间(回传数据给代理超时)
proxy_buffering on; # nginx会把后端返回的内容先放到缓冲区中,然后再返回给客户端,边收边传,不是全部接收再传给客户端
proxy_buffers_size 4k; # 设置nginx代理保存用户头信息的缓存区大小
proxy_buffers 8 8k; # 设置nginx代理缓冲区大小(8*8 = 64k)
...
}
}
2. 对于fastcgi服务器,需要设置fastcgi_keep_conn以便保持长连接
vim /etc/nginx/conf.d/zh.nana.com.conf
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;
# 需要解析的文件都会传给变量名SCRIPT_FILENAME,php服务端会读取该变量,解析变量里面的文件内容,解析完成再传给Nginx。
fastcgi_keep_conn on; # 开启php长连接
fastcgi_connect_timeout 60s; # 连接超时时间
include fastcgi_params;
...
}
}
注意:
Nginx作为静态资源web服务器,用于静态资源处理,传输非常的高效。
静态资源指的是,非Web服务器端运行处理而生成的文件
静态资源类型 | 种类
浏览器渲染 | html、css、js
图片文件 | jpeg、gif、png
视频文件 | flv、Mp4、avi
其他文件 | txt、doc、pd
1. 静态资源缓存
浏览器缓存设置用于提高网站性能,尤其是新闻网站,图片一旦发布,改动的可能是非常小的。所以我们希望能否用户访问一次后,图片缓存在用户的浏览器长时间缓存。
浏览器是有自己的缓存机制,它是基于HTTP协议缓存机制来实现的,在HTTP协议中有很多头信息,那么实现浏览器的缓存就需要依赖特殊的头信息来与服务器进行特殊的验证,如:Expires(http/1.0);Cache-control(http/1.1)。
浏览器缓存过期校验检查机制,原理如下:
1.1 设置文件缓存时间(响应码304)
1. 修改Nginx配置文件
vim /etc/nginx/conf.d/try.conf
server {
listen 80;
server_name _;
root /code;
location / {
index index.html;
}
location ~ \.*(png|jpg|gif|jpeg)$ {
expires 1d; # 设置静态资源缓存时间为1天
add_header test $host; # 添加头信息
}
}
2. 重启Nginx服务
systemctl restart nginx
1. 修改Nginx配置文件
vim /etc/nginx/conf.d/try.conf
server {
listen 80;
server_name _;
root /code;
location / {
index index.html;
}
location ~ \.*(png|jpg|gif|jpeg)$ {
add_header test $host;
add_header Cache-Control no-store;
add_header Pragma no-cache;
}
}
2. 重启Nginx服务
systemctl restart nginx
2. 静态文件资源读取
传统文件读取方式:硬件--->内核--->用户空间--->程序空间--->程序内核空间--->套接字服务
。
开启sendfile服务后:硬件--->内核--->程序内核空间--->套接字服务
。
开启sendfile服务
- Nginx主配置文件(默认开启sendfile)
vim /etc/nginx/nginx.conf
...
sendfile on;
...
将多个包一次性发送,用户提升网络传输效率,大文件推荐打开,需要先开启sendfile才行
- Nginx主配置文件
vim /etc/nginx/nginx.conf
...
sendfile on;
tcp_nopush on;
...
提高网络传输实时性,需要开启keepalive(与tcp_nopush相反,不要同时打开)
- Nginx主配置文件
vim /etc/nginx/nginx.conf
...
tcp_nodelay on;
keepalive_timeout 65;
...
3. 静态资源压缩
Nginx将响应报文发送至客户端之前启用压缩功能,然后进行传输,这能够有效的节约宽带,并提高响应至客户端的速度。
gzip压缩传输,传输前压缩,传输后浏览器解压
1. 上传一张图片
cd /code
rz -E 40x.jpg
ll -h # 查看我们上传至服务器图片的大小21K
# -rw-r--r-- 1 root root 21K Apr 3 22:12 40x.jpg
2. 查看压缩类型的文件
vim /etc/nginx/mime.types
...
image/gif gif;
image/jpeg jpeg jpg;
image/png png;
...
3. 修改Nginx配置文件
vim /etc/nginx/conf.d/try.conf
server {
listen 80;
server_name _;
root /code;
location / {
index index.html;
}
# 压缩图片
location ~ \.*(png|jpg|gif|jpeg)$ {
gzip on; # 开启压缩功能
gzip_types image/jpeg image/gif image/png; # 压缩文件的类型
gzip_comp_level 9; # 压缩的等级(压缩等级越大,压缩的空间大小越大,9是最大等级)
gzip_http_version 1.1; # 压缩http的版本
}
# 压缩文件
location ~ \.*(txt|xml|html|js|css)$ {
gzip on; # 开启压缩功能
gzip_types text/plain text/html; # 压缩文件的类型
gzip_comp_level 9; # 压缩的等级(压缩等级越大,压缩的空间大小越大,9是最大等级)
gzip_http_version 1.1; # 压缩http的版本
}
}
4. 重启Nginx服务
systemctl restart nginx
测试
4. 防止资源盗链
防盗链,指的是防止资源被其他网站恶意盗用,如图所示:
基础防盗链设置思路:主要是针对客户端请求过程中所携带的一些Header信息来验证请求的合法性,比如客户端在请求的过程中都会携带referer信息(referer会告诉服务器请求从哪一个页面过来的)。优点是规则简单,配合和使用都很方便,缺点是防盗链所依赖的Referer验证信息是可以伪造的(可以通过代码对上一个请求来源页面的域名进行修改),所以通过Referer信息防盗链并非100%可靠,但是它能够限制大部分盗链的情况。
1.在盗链服务器上准备html文件,偷取Web03服务器(nana.com)网站上的图片
- web01服务器
1. 修改Nginx配置文件
vim /etc/nginx/conf.d/dl.conf
server {
listen 80;
server_name dl.com;
root /code;
location / {
index index.html index.html;
}
}
2. 创建nginx数据文件
vim /code/referer_test.html
"utf-8">
lala.com</title>
</head>
"background-color:red;">
"http://nana.com/a.jpg">
</body>
2. 重启Nginx服务
systemctl restart nginx
在本机添加域名解析
C:\Windows\System32\drivers\etc
在hosts文件添加域名解析(注释掉本机其他ip与域名之间的对应关系)
192.168.15.7 dl.com
2.使用浏览器能正常访问到偷链的资源
- web03服务器
1. 创建Nginx数据文件
cd /code/
rz -E a.jpg
2. 修改Nginx配置文件
vim /etc/nginx/conf.d/nana.conf
server {
listen 80;
server_name nana.com;
root /code;
location / {
index index.html index.html;
}
}
3. 重启Nginx服务
systemctl restart nginx
在本机添加域名解析
C:\Windows\System32\drivers\etc
在hosts文件添加域名解析(注释掉本机其他ip与域名之间的对应关系)
192.168.15.9 nana.com
3.在web03服务器(nana.com)上配置防盗链(返回403或者是其他图片)
- Web03服务器
1. 创建Nginx数据文件
cd /code
rz -E b.jpg
2. 修改Nginx配置文件
vim /etc/nginx/conf.d/nana.conf
server {
listen 80;
server_name nana.com;
root /code;
location / {
index index.html index.html;
}
location ~ .*\.(jpg|jpeg|gif|png)$ {
# 指定合法的来源referer(上一个页面的来源的域名),匹配成功(*.nana.com)这个变量被设置为0,匹配失败设置为1
valid_referers none blcoked *.nana.com;
if ($invalid_referer) {
# return 403;
rewrite ^(.*)$ /b.jpg break;
}
}
}
2. 重启Nginx服务
systemctl restart nginx
以上配置含义表示,所有来自*.nana.com都可以访问到当前站点的图片,如果来源域名不在这个列表中,那么$invalid_referer等于1,
在if语句中返回一个/code/b.jpg给用户,这样用户便会看到一个b.jpg的图片页面。
4.设置某些网站能够使用(盗链)资源
- web03服务器
1. 修改Nginx配置文件
vim /etc/nginx/conf.d/nana.conf
server {
listen 80;
server_name nana.com;
root /code;
location / {
index index.html index.html;
}
location ~ .*\.(jpg|jpeg|gif|png)$ {
# server_names设置哪些网站能够使用(盗链)资源
valid_referers none blcoked *.nana.com server_names dl.com ~\.google\. ~\.baidu\.;
if ($invalid_referer) {
rewrite ^(.*)$ /b.jpg break;
}
}
}
2. 重启Nginx服务
systemctl restart nginx
5. 允许跨域访问
什么是跨站访问,当我们通过浏览器访问a网站时,同时会利用ajax或其他方式,同时也请求b网站,这样的话就出现了请求一个页面,使用2个域名,这种方式对浏览器来说默认是禁止。
那么Nginx允许跨站访问与浏览器有什么关系呢,因为浏览器会读取Access-Control-Allow-Origin
的头信息,如果服务端允许,则浏览器不会进行拦截。
1.模拟跨域访问问题
- Web01服务器
1. 修改Nginx配置文件
server {
listen 80;
server_name dl.com;
root /code;
location / {
index index.html index.html;
}
}
2. 配置Nginx数据文件
vim /code/http.html
"en">
"UTF-8">
测试ajax和跨域访问</title>