性能优化概述
在做性能优化前重点需要考虑哪些方面,和需要了解哪些方面?
首先需要了解我们当前系统的结构和瓶颈,了解当前使用的是什么,运行的是什么业务,都有哪些服务,了解每个服务最大能支撑多少并发。比如nginx作为静态资源服务并发是多少,最高瓶颈在哪里,能支持多少qps(每秒查询率)的访问请求,那我们怎么得出这组系统结构瓶颈呢,比如top查看系统的CPU负载、内存使用率、总得运行进程等,也可以通过日志去分析请求的情况,当然也可以通过我们前面介绍到的stub_statius模块查看当前的连接情况,也可以对线上的业务进行压力测试(低峰期),去了解当前这套系统能承担多少的请求和并发,已做好响应的评估。这个是我们做性能优化最先考虑的地方。
其次我们需要了解业务模式,虽然我们是做性能优化,但每一个性能的优化都是为业务所提供的服务的,我们需要了解每个业务接口的类型,比如:电商网站中的抢购模式,这种情况下面,平时没什么流量,但到了抢购时间流量会突增。
我们还需要了解系统层次化的结构,比如:我们使用nginx做的是代理、还是动静分离、还是后端直接服务用户,那么这个就需要我们对每一层做好相应的梳理。以便更好的服务业务。最后我们需要考虑性能与安全,往往注重了性能,但是忽略了安全。往往过于注重安全,对性能又会产生影响。比如:我们在设计防火墙功能时,检测过于严密,这样就会给性能带来影响。那么如果对于性能完全追求,却不顾服务的安全,这个也会造成很大的隐患,所以需要评估好两者的关系,把握好两者的孰重孰轻。以及整体的相关性,权衡好对应的点。
从OSI模型考虑优化方向
硬件 代理(CPU) 静态(磁盘IO) 动态(cpu、内存)
网络 带宽、丢包、延迟
系统 文件描述符(文件句柄数)
应用 服务与服务保持长连接 http1.1
服务 静态资源服务优化
影响性能的方式(了解)
网络
网络的流量
网络丢包
系统
硬件是否有磁盘损坏、磁盘速率
系统的负载、内存、系统稳定性
服务
连接优化、请求优化
根据业务形态做对应的服务设置
程序
接口性能
处理速率
程序执行效率
数据库
ab压测工具
简介
在系统业务量没有增长之前,我们就要做好相应的准备工作,以防患业务量突增带来的接口压力,所以对于接口压力测试就显得非常重要了,我们首先要评估好系统压力,然后使用工具检测当前系统情况,是否能满足对应压力的需求。
原理
ab命令会创建多个并发访问线程,模拟多个访问者同时对某一URL地址进行访问。它的测试目标是基于URL的,因此,它既可以用来测试apache的负载压力,也可以测试nginx、lighthttp、tomcat、IIS等其它Web服务器的压力。ab命令对发出负载的计算机要求很低,它既不会占用很高CPU,也不会占用很多内存。但却会给目标服务器造成巨大的负载,其原理类似CC攻击。自己测试使用也需要注意,否则一次上太多的负载。可能造成目标服务器资源耗完,严重时甚至导致死机。
需要了解的名词
吞吐率(Requests per second)
服务器并发处理能力的量化描述,单位是reqs/s,指的是在某个并发用户数下单位时间内处理的请求数。某个并发用户数下单位时间内能处理的最大请求数,称之为最大吞吐率。
并发连接数(The number of concurrent connections)
并发连接数指的是某个时刻服务器所接受的请求数目,简单的讲,就是一个会话。
并发用户数(Concurrency Level)
要注意区分这个概念和并发连接数之间的区别,一个用户可能同时会产生多个会话,也即连接数。在HTTP/1.1下,IE7支持两个并发连接,IE8支持6个并发连接,FireFox3支持4个并发连接,所以相应的,我们的并发用户数就得除以这个基数。
用户平均等待时间(Time per request)
计算公式:处理完成所有请求数所花费的时间/(总请求数/并发用户数),即:
Time per request=Time taken for tests/(Complete requests/Concurrency Level)
服务器平均等待时间(Time per request:across all concurrent requests)
计算公式:处理完成所有请求数所花费的时间/总请求数,即:
Time taken for/testsComplete requests
可以看到,它是吞吐率的倒数。
同时,它也等于用户平均请求等待时间/并发用户数,即
Time per request/Concurrency Level
使用
安装
yum install -y httpd-tools使用方式
[root@web01 conf.d]# ab
ab: wrong number of arguments
Usage: ab [options] [http[s]://]hostname[:port]/path
#例
[root@web01 ~]# ab -n 200 -c 2 http://127.0.0.1/
#参数
#-n 要执行的请求数
#-c 请求的并发数
#-k 是否开启长连接查看结果

系统性能优化
文件句柄
Linux一切皆文件,文件句柄可以理解为就是一个索引,文件句柄会随着我们进程的调用频繁增加,系统默认文件句柄是有限制的,不能让一个进程无限的调用,所以我们需要限制每个 进程和每个服务使用多大的文件句柄,文件句柄也是必须要调整的优化参数
文件句柄的设置方式:
系统全局性修改。
用户局部性修改。
进程局部性修改。
[root@lb01 ~]# vim /etc/security/limits.conf
1、系统全局性修改。
# * 代表所有用户
* soft nofile 25535
* hard nofile 25535
2.用户局部性修改
#针对root用户,soft仅提醒,hard限制,nofile打开最大文件数
root soft nofile 65535
root hard nofile 65535
3.进程局部性修改
#针对nginx进程,nginx自带配置
worker_rlimit_nofile 30000内核参数
4.调整内核参数:让time_wait状态重用(端口重用)[flag]
[root@web01 ROOT]# vim /etc/sysctl.conf
net.ipv4.tcp_tw_reuse = 1 # 开启端口复用
net.ipv4.tcp_timestamps = 0 # 禁用时间戳
[root@web01 ROOT]# sysctl -p #可以查看我们添加的内核参数
[root@web01 ROOT]# sysctl -a #可以查看所有内核参数代理服务优化
通常nginx作为代理服务,负责转发用户的请求,那么在转发的过程中建议开启HTTP长连接,用于减少握手次数,降低服务器损耗。
长连接配置示例(应用方面优化)
Syntax: keepalive connection;
Default: -
Context: upstream
#该指令出现在1.1.4版中
配置nginx代理服务使用长连接方式
upstream http_backend {
server 127.0.0.1:8080;
keepalive 16; #长连接
}
server {
...
location /http/ {
proxy_pass http://http_backend;
proxy_http_version 1.1; #对于http协议应该指定为1.1
proxy_set_header Connection ""; #清除“connection”头字段
proxy_next_upstream error timeout http_500 http_502 http_503 http_504; #平滑过渡
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响应的数量和大小
...
}
}对应fastcgi服务器,需要开启fastcgi_keep_co以便保持长连接
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;
...
}
}keepalive_requests设置通过一个keepalive连接提供的最大请求数,在发出最大请求数后,将关闭连接
Syntax: keepalive_requests number;
Default: keepalive_requests 100;
Context: upstreamkeepalive_timeout设置超时,再次期间与代理服务器的空闲keepalive连接将保持打开状态
Syntax: keepalive_timeout timeout;
Default: keepalive_timeout 60s;
Context: upstream静态资源优化
nginx处理静态资源来说是非常高效的。静态资源一般是指非WEB服务器运行处理生成的文件
静态资源类型 | 种类 |
|---|---|
浏览器渲染 | HTML、CSS、JS |
图片文件 | JPEG、GIF、PNG |
视频文件 | FLV、MP4、AVI |
其他文件 | TXT、DOC、PDF...... |

浏览器缓存过期校验机制
说明:
浏览器请求服务器会先进行Expires、Cache-Control的检查,检查缓存是否过期,如果没有过期则直接从缓存文件中读取。
如果缓存过期首先检查是否存在etag,如果存在那么客户端会向web服务器请求If-None-Match,与etag值进行比对,有服务器决策返回200还是304。
如果etag不存在,则进行last-Modified检查,客户端会向web服务器请求if-Modified-Since,与last-Modified进行比对,有服务器决策返回200还是304。
Last-Modified:服务器上文件的最后修改时间
Etag:文件标识
Expires:本地缓存目录中,文件过期的时间(由服务器指定具体的时间)
Cache-control:本地缓存目录中,文件过期的时间(由服务器指定过期的间隔时间,由于浏览器根据间隔生成具体的时间
配置静态缓存expires
#语法
#作用:添加Cache-Control Expires头
Syntax: expires [modified] time;
epoch | max | off;
Default: expires off;
Context: http, server, location, if in location
#案例
server {
listen 80;
server_name static.oldboy.com;
#设置缓存7天
location ~ .*\.(jpg|gif|png)$ {
expires 7d;
}
location ~ .*\.(js|css)$ {
expires 30d;
}
}
#案例
#取消js、css、html等静态文件缓存
location ~ .*\.(js|css|html)$ {
add_header Cache-Control no-store;
add_header Pragma no-cache;
}静态文件读取
Syntax: sendfile on | off;
Default: sendfile off;
Context: http, server, location, if in location将多个包一次发送,用于提升网络传输效率,大文件推荐打开,需要开启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静态资源压缩
Nginx将响应报文发送至客户端之前启用压缩功能,然后进行传输,这能够有效地节约带宽,并提高响应至客户端的速度。
文件压缩对图片类压缩的比例并不明显,但是对于文件压缩的比例很高

gzip压缩配置
#gzip传输压缩,传输前压缩,传输后解压
Syntax: gzip on | off;
Default: gzip off;
Context: http, server, location, if in location
#gzip压缩哪些文件
Syntax: gzip_types mime-type ...;
Default: gzip_types text/html;
Context: http, server, location
#gzip压缩比率,加快传输,但压缩本身比较耗费服务器性能
Syntax: gzip_comp_level level;
Default:gzip_comp_level level 1;
Context: http, server, location
#gzip压缩协议版本,压缩使用在http哪个协议,主流选择1.1版本
Syntax: gzip_http_version 1.0 | 1.1;
Default:gzip_http_version 1.1;
Context: http, server, location
#案例
server {
listen 80;
server_name try.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;
}
}防盗链
盗链的含义
服务提供商自己不提供服务的内容,通过技术手段去使用别的网站的资源
什么是防盗链?
顾名思义,就是指防止资源被其他网站恶意盗用。
配置思路
#语法
Syntax: valid_referers none | blocked | server_name | string ...;
Default: -;
Context: server, location
#none: referer来源头部为空的情况
#blocked: referer来源头部不为空,这些都不以http://或者https://开头
#server_name: 来源头部信息包含当前域名,可以正则匹配
#配置案例
location ~ .*\.(jpg|png|gif) {
root /var/www/wordpress/wp-content/extra/;
valid_referers none blocked *.test.com;
if ( $invalid_referer ) {
return 403;
}
}
#以上配置含义表示,所有来自*.test.com都可以访问到当前站点的图片,如果来源域名不在这个列表中,那么$invalid_referer等于1,在if语句中返回一个403个客户,这样用户便会看到一个403的页面
#案例2
#如果不使用return而是用rewrite,那么盗链图片会返回一个pei.jpg给用户
location ~ .*\.(jpg|png|gif) {
root /var/www/wordpress/wp-content/extra/;
valid_referers none blocked *.test.com;
if ( $invalid_referer ) {
rewrite ^(.*)$ /Picture/daolian1.gif break;
}
}
#案例三
#如果希望某些网站可以盗链
location ~ .*\.(jpg|png|gif) {
root /data;
valid_referers none blocked *.test.com server_name ~\.google\. ~\.baidu\.;
if ( $invalid_referer ) {
return 403;
}
}允许跨域访问
什么是跨域访问,当我们通过浏览器访问a网站时,同时会利用到ajax或其他方式,同时也请求b网站,这样的话就出现了请求一个页面,使用了两个域名,这种方式对浏览器来说默认是禁止的。
那Nginx语序跨站访问与浏览器有什么关系呢,因为浏览器会读取Access-Control-Allow-Origin的头信息,如果服务端允许,则浏览器不会进行拦截。
Syntax: add_header name value [always];
Default: -;
Context: http, server, location, if in location配置案例
#注意:要在被关联的服务器配置
server {
listen 80;
server_name web.test.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;
}
}CPU亲和度配置
CPU亲和(affinity)减少进程之间不断频繁切换,减少性能损耗,其实现原理是建CPU核心和Nginx工作进程绑定方式,把每个worker进程固定到对应的cpu上执行,减少切换CPU的cache miss,获得更好的性能

查看当前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个核心将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;查看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通用优化(参考)
[root@nginx ~]# cat 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;
}Nginx安全与优化总结
CPU亲和、worker进程数、调整每个worker进程打开的文件数
使用额pool网络模型、调整每个worker进程的最大连接数
文件的高效读取sendfile、no铺设
文件的传输实时性、nodealy
开启tcp长连接,以及长连接超时时间keepalived
开启文件传输压缩gzip
开启静态文件expires缓存
异常nginx版本号
禁止通过ip地址访问,禁止恶意域名解析,只允许域名访问
配置防盗链、以及跨域访问
防DDOS、cc攻击,限制单IP并发连接,以及http请求
优雅限制nginx错误页面
nginx加密传输https优化
nginx proxy_cache、fastcgi_cache、uwsgi_cache 缓存,第三方工具(squid、varnish)
评论区