在做性能优化前, 我们需要对如下进⾏考虑
1.当前系统结构瓶颈
观察指标
压⼒测试 ab(httpd-tools) webbanch
2.了解业务模式
接⼝业务类型
系统层次化结构
3.性能与安全
性能好安全弱
安全好性能低
1.安装压⼒测试⼯具 ab
yum install httpd-tools -y
2.了解压测⼯具使⽤⽅式
ab -n 200 -c 2 http://127.0.0.1/
-n 总的请求次数
-c 并发请求数
-k 是否开启⻓连接
3. 配置 Nginx 静态⽹站与 tomcat 动态⽹站环境
给Nginx准备静态⽹站
mkdir -p /soft/code
echo " Ab Load
" > /soft/code/bgx.html
给Tomcat准备静态⽹站⽂件
yum -y install tomcat
mkdir -p /usr/share/tomcat/webapps/ROOT/
echo " Ab Load
" > /usr/share/tomcat/webapps/ROOT/bgx.html
vi /usr/local/nginx/conf/nginx.conf
root /soft/code;
try_files $uri $uri/ @java_page;
index index.jsp index.html;
}
location @java_page{
proxy_pass http://192.168.1.1:8080;
}
}
##进⾏压⼒测试
ab -n2000 -c2 http://192.168.1.1/bgx.html
ab -n2000 -c2 http://192.168.1.1:8080/bgx.html
Server Software: nginx/1.18.0
Server Hostname: 192.168.1.1
Server Port: 80
Document Path: /bgx.html
Document Length: 19 bytes
Concurrency Level: 2
Time taken for tests: 0.104 seconds ##总花费总时见
Complete requests: 2000 ##总请求数
Failed requests: 0 ##请求失败数
Write errors: 0
Total transferred: 500000 bytes
HTML transferred: 38000 bytes
Requests per second: 19140.59 [#/sec] (mean) ##每秒多少请求/s(总请求出/总共完成的时间)
Time per request: 0.104 [ms] (mean) ##客户端访问服务端, 单个请求所需花费的时间
Time per request: 0.052 [ms] (mean, across all concurrent requests) ##服务端处理请求的时间
Transfer rate: 4673.00 [Kbytes/sec] received ##判断⽹络传输速率, 观察⽹络是否存在瓶颈
5.将 nginx 下的 bgx ⽂件移⾛, 再次压测会由 tomcat 进⾏处理
影响性能⽅便整体关注
1.⽹络
⽹络的流量
⽹络是否丢包
这些会影响http的请求与调⽤
2.系统
硬件有没有磁盘损坏,磁盘速率
系统负载、内存、系统稳定性
3.服务
连接优化、请求优化
根据业务形态做对应的服务设置
4.程序
接⼝性能
处理速度
程序执⾏效率
5.数据库
每个架构服务与服务之间都或多或少有⼀些关联, 我们需要将整个架构进⾏分层, 找到对应系统或服务的短板, 然后进⾏优化
⽂件句柄, Linux⼀切皆⽂件,⽂件句柄可以理解为就是⼀个索引
⽂件句柄会随着我们进程的调⽤频繁增加
系统默认对⽂件句柄有限制,不能让⼀个进程⽆限的调⽤
需要限制每个进程和每个服务使⽤多⼤的⽂件句柄
⽂件句柄是必须要调整的优化参数
设置⽅式
系统全局性修改
⽤户局部性修改
Error:too many open files
vim /etc/security/limits.conf
//针对root⽤户
root soft nofile 65535
root hard nofile 65535
//所有⽤户, 全局
* soft nofile 25535
* hard nofile 25535
//对于Nginx进程
worker_rlimit_nofile 45535;
//root⽤户
//soft提醒
//hard限制
//nofile⽂件数配置项
//65535
CPU 亲和, 减少进程之间不断频繁迁移, 减少性能损耗
1.查看当前 CPU 物理状态
[root@nginx ~]# lscpu |grep "CPU(s)"
CPU(s): 24
On-line CPU(s) list: 0-23
NUMA node0 CPU(s): 0,2,4,6,8,10,12,14,16,18,20,22
NUMA node1 CPU(s): 1,3,5,7,9,11,13,15,17,19,21,23
//2颗物理cpu,每颗cpu12核⼼, 总共24核⼼
2.将 Nginx worker 进程绑到不同的核⼼上
//启动多少worker进程, 官⽅建议和cpu核⼼⼀致, 第⼀种绑定组合⽅式
#worker_processes 24;
#worker_cpu_affinity 000000000001 000000000010 000000000100 000000001000 0000000100
00 000000100000 000001000000 000010000000 000100000000 001000000000 010000000000 10
000000000;
//第⼆种⽅式
#worker_processes 2;
#worker_cpu_affinity 101010101010 010101010101;
//最佳⽅式绑定⽅式
worker_processes auto;
worker_cpu_affinity auto;
3.查看 nginx worker 进程绑定⾄对应 cpu
ps -eo pid,args,psr|grep [n]ginx
4. Nginx 通⽤优化配置⽂件
[root@nginx ~]# cat nginx.conf
user nginx;
worker_processes auto;
worker_cpu_affinity auto;
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;
#调整⾄1w以上,负荷较⾼建议2-3w以上
worker_rlimit_nofile 35535;
events {
use epoll;
#限制每个进程能处理多少个连接请求,10240x16
worker_connections 10240;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
#统⼀使⽤utf-8字符集
charset 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"';
access_log /var/log/nginx/access.log main;
#Core module
sendfile on;
#静态资源服务器建议打开
tcp_nopush on;
#动态资源服务建议打开,需要打开keepalived
tcp_nodelay on;
keepalive_timeout 65;
#Gzip module
gzip on;
gzip_disable "MSIE [1-6]\.";
gzip_http_version 1.1;
#Virtal Server
include /etc/nginx/conf.d/*.conf;
}
1.Nginx 多个相同 Server_name 优先级
2.location 匹配优先级
3.try_files使⽤
4.Ngnx的alias和root区别
Nginx 多个相同 Server_name 优先级
1.环境准备
mkdir /soft/code{
1..3} -p
for i in {
1..3};do echo "Code $i
" > /soft/code"$i"/index.html;done
2.修改配置文件
vi /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name testserver1 192.168.1.1;
location / {
root /soft/code1;
index index.html;
}
}
server {
listen 80;
server_name testserver2 192.168.1.1;
location / {
root /soft/code2;
index index.html;
}
}
server {
listen 80;
server_name testserver3 192.168.1.1;
location / {
root /soft/code3;
index index.html;
}
}
nginx -t ##检查语法
systemctl restart nginx ##重启nginx服务
3.测试访问效果
[root@localhost ~]# curl 192.168.1.1
Code 1</h1>
当servername一样的时候,访问的优先级从上到下
= 正则匹配 ^~ ~ ~* 默认匹配
1.实例准备
vi /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name 192.168.1.1;
root /soft;
index index.html;
location = /code1/ {
rewrite ^(.*)$ /code1/index.html break;
}
location ~ /code* {
rewrite ^(.*)$ /code3/index.html break;
}
location ^~ /code {
rewrite ^(.*)$ /code2/index.html break;
}
}
[root@localhost ~]# curl http://192.168.1.1/code1
Code 2</h1>
systemctl restart nginx
测试效果
[root@localhost ~]# curl http://192.168.1.1/code1
Code 3</h1>
systemctl restart nginx
测试效果
[root@localhost ~]# curl http://192.168.1.1/code1
Code 2</h1>
Break:页面找不到,停止匹配
Last: 页面找不到,继续向下匹x配
nginx 的 try_files 按顺序检查⽂件是否存在
location /{
try_files $uri $uri/ /index.php;
}
http://192.168.1.1/zps
$uri 判断zps目录是否存在
$uri/ 如果zps目录存在,那么就将zps目录下的index.html文件解析之后返回给客户端
/index.php 如果index.html不存在,那么就看zps目录下是否存在index.php页面
#1.检查⽤户请求的uri内容是否存在本地,存在则解析
#2.将请求加/, 类似于重定向处理
#3.最后交给index.php处理
1.演示环境准备
echo "Try-Page" > /usr/local/nginx/html/index.html
echo "Tomcat-Page" > /soft/app/apache-tomcat-9.0.7/webapps/ROOT/index.html
sh /soft/app/apache-tomcat-9.0.7/bin/startup.sh
netstat -lntp|grep 8080
2.配置 Nginx 的 tryfiles
vi /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name 192.168.1.1;
root /soft/code;
index index.html;
location / {
try_files $uri @java_page;
}
location @java_page {
proxy_pass http://127.0.0.1:8080;
}
}
nginx -s reload ##重启Nginx
3.测试 tryfiles
[root@Nginx ~]# curl http://192.168.1.1/index.html
Try-Page
4.将/soft/code/index.html⽂件移⾛
mv /soft/code/{
index.html,index.html_bak}
5.发现由Tomcat吐回了请求
[root@Nginx ~]# curl http://192.168.1.1/index.html
Tomcat-Page
root 路径配置
//Nginx的root配置
[root@Nginx ~]# vi /usr/local/nginx/conf/nginx.conf
server {
listen 80;
index index.html;
location /request_path/code/ {
root /local_path/code/;
}
}
//请求测试
[root@Nginx conf.d]# curl http://192.168.1.1/request_path/code/index.html
Root
//实际请求本地⽂件路径为
/local_path/code/'request_path/code'/index.html
alias 路径配置
[root@Nginx ~]# mkdir /local_path/code/request_path/code/ -p
[root@Nginx ~]# echo "Alias" > /local_path/code/index.html
//配置⽂件
[root@Nginx ~]# vi /usr/local/nginx/conf/nginx.conf
server {
listen 80;
index index.html;
location /request_path/code/ {
alias /local_path/code/;
}
}
//测试访问
[root@Nginx ~]# curl http://192.168.1.1/request_path/code/index.html
Alias
//实际访问本地路径
/local_path/code/'index.html'
Root和alias都是用来指定网页存放路径的,只不过root可以用相对路径,alias必须是绝对路径
Nginx 传递⽤户的真实IP地址
$remote_addr 只能获取到最近⼀台服务器访问IP
x_forwarded_for 头部信息容易被篡改
获取客户端真实的IP地址?
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
200 正常请求
301 永久跳转
302 临时跳转
400 请求参数错误
401 账户密码错误(authorization required)
403 权限被拒绝(forbidden)
404 ⽂件没找到(Not Found)
413 ⽤户上传⽂件⼤⼩限制(Request Entity Too Large)
502 后端服务⽆响应(bad gateway)
504 后端服务执⾏超时
如果⼀栋⼤厦⾥所有⼯作⼈员通过1个IP公⽹接⼝上⽹, 总共100个设备, 当所有⼈同时请求⼀个⽹ 站, 并且刷新了5次, 那么请求pv、ip、uv
pv:页⾯浏览量 500
uv:唯⼀设备100
ip:唯⼀出⼝ 1
1.DNS流程
1.查询本地Hosts
2.请求本地localDNS
3.返回对应的IP
2.HTTP连接
1.建⽴TCP三次握⼿,发送请求内容, 请求头、请求的⾏、请求的主体
2.将请求传递给负载均衡, 负载均衡做对应的调度
3.如果请求的是静态页⾯, 那么调度⾄对应的静态集群组即可
4.如果请求的是动态页⾯, 将请求调度⾄动态集群组
1.如果仅仅是请求页⾯, 可能会经过Opcache
2.如果请求页⾯需要查询数据库, 或者是往数据库插⼊内容
3.检查对应的操作是查询还是写⼊, 如果是查询数据库
4.检查查询的内容是否有被缓存, 如有缓存则返回
5.检查查询语句, 将查询结果返回
6.内存缓存Redis缓存对应的查询结果
7.返回对应客户端请求的内容⾄于WEB节点
8.WEB节点收到请求后返回内容⾄负载均衡
9.负载均衡返回客户端内容, TCP四次断开
3.HTTP断开连接
1.按照分层结构
CDN层->负载层->WEB层->存储层->缓存层->数据库层
同时需要注意, 每⼀层都有对应的缓存机制
Nginx优化
1.gzip压缩
2.expires静态⽂件缓存
3.调整⽹络IO模型,调整Nginx worker进程的最⼤连接数
5.隐藏Nginx名称和版本号
6.配置防盗链,防⽌资源被盗⽤
7.禁⽌通过IP地址访问,禁⽌恶意域名解析,只允许域名访问
8.防DDOS、cc攻击, 限制单IP并发请求连接
9.配置错误页⾯,根据错误代码指定⽹页反馈⽤户
10.限制上传资源⽬录被程序访问,防⽌⽊马⼊侵系统
11.Nginx加密传输优化