性能优化概述
1.我们需要了解的
1、首先需要了解我们当前系统的结构和瓶颈,了解当前使用的是什么,运行的是什么业务,都有哪些服务,了解每个服务最大能支撑多少并发。比如nginx作为静态资源服务并发是多少,最高瓶颈在哪里,能支持多少qps(每秒查询率)的访问请求,那我们怎么得出这组系统结构瓶颈呢,比如top查看系统的CPU负载、内存使用率、总得运行进程等,也可以通过日志去分析请求的情况,当然也可以通过我们前面介绍到的stub_status模块查看当前的连接情况,也可以对线上的业务进行压力测试(低峰期),去了解当前这套系统能承担多少的请求和并发,已做好响应的评估。这个是我们做性能优化最先考虑的地方。
2、其次我们需要了解业务模式,虽然我们是做性能优化,但每一个性能的优化都是为业务所提供的服务的,我们需要了解每个业务接口的类型,比如:电商网站中的抢购模式,这种情况下面,平时没什么流量,但到了抢购时间流量会突增。
我们还需要了解系统层次化的结构,比如:我们使用nginx做的是代理、还是动静分离、还是后端直接服务用户,那么这个就需要我们对每一层做好相应的梳理。以便更好的服务业务。
3、最后我们需要考虑性能与安全,往往注重了性能,但是忽略了安全。往往过于注重安全,对性能又会产生影响。比如:我们在设计防火墙功能时,检测过于严密,这样就会给性能带来影响。那么如果对于性能完全追求,却不顾服务的安全,这个也会造成很大的隐患,所以需要评估好两者的关系,把握好两者的孰重孰轻。以及整体的相关性,权衡好对应的点。
1.首先需要了解我们当前系统的结构和瓶颈
2.分析服务的限制和使用情况
3.了解业务模式
4.了解系统层次化的结构
5.考虑性能与安全
2.从哪些方面入手进行优化
OSI 七层模型:物理层,数据链路层,网络层,传输层,会话层,表示层,应用层
1.硬件 如果nginx做代理(CPU),静态资源(磁盘读写性能,磁盘大小),动态资源(CPU,内存)
2.网络 带宽,丢包,延迟
3.系统 文件描述符(文件句柄数)
4.应用 服务与服务保持长连接
5.服务 静态资源服务优化
压力测试工具(ab)
1.安装ab压力测试工具
[root@web01 ~]# yum install -y httpd-tools
2.测试工具参数
[root@web01 ~]# ab -n 200 -c 2 http://blog.linux.com/
-n 指定请求次数
-c 指定并发数
-k 开启长连接
[root@web01 ~]# ab
Usage: ab [options] [http[s]://]hostname[:port]/path
3.配置nginx静态网站
#配置nginx
[root@web01 conf.d]# vim ab.linux.com.conf
server {
listen 80;
server_name ab.linux.com;
location / {
root /code/ab;
try_files $uri $uri/ @java;
}
location @java {
proxy_pass http://127.0.0.1:8080;
}
}
#配置nginx站点目录文件
[root@web01 conf.d]# echo linux_nginx > /code/ab/index.html
[root@web01 conf.d]# systemctl restart nginx
4.压力测试静态网站
[root@web01 conf.d]# ab -n 10000 -c 200 http://ab.linux.com/index.html
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 ab.linux.com (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.16.1
Server Hostname: ab.linux.com
Server Port: 80
Document Path: /index.html
Document Length: 12 bytes
Concurrency Level: 200
Time taken for tests: 4.195 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 2420000 bytes
HTML transferred: 120000 bytes
Requests per second: 2383.81 [#/sec] (mean)
Time per request: 83.899 [ms] (mean)
Time per request: 0.419 [ms] (mean, across all concurrent requests)
Transfer rate: 563.36 [Kbytes/sec] received
[root@web01 conf.d]#
5.配置tomcat静态网站
#1.下载或上传tomcat包
[root@web01 ~]# mkdir /service
[root@web01 ~]# cd /service
[root@web01 service]# rz apache-tomcat-8.5.51.tar.gz
#2.解压代码包
[root@web01 service]# tar xf apache-tomcat-8.5.51.tar.gz
#3.配置java环境
1.上传并解压至指定文件夹
[root@web01 service]# tar xf jdk-8u40-linux-x64.gz -C /service/
[root@web01 service]# mv jdk1.8.0_40 java1.8
2.修改添加环境变量
[root@web01 service]# vim /etc/profile.d/java.sh
export JAVA_HOME=/service/java1.8
export JRE_HOME=/service/java1.8/jre
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$PATH:$JAVA_HOME/bin
[root@web01 service]# source /etc/profile
#4.配置tomcat页面
[root@web01 service]# echo "linux_tomcat" > apache-tomcat-8.5.51/webapps/ROOT/index.html
#5.启动tomcat,启动的时候最好看着日志
[root@web01 service]# /service/apache-tomcat-8.5.51/bin/startup.sh && tail -f /service/apache-tomcat-8.5.51/logs/catalina.out
6.压力测试tomcat处理静态网站
[root@web01 service]# ab -n 10000 -c 200 http://ab.linux.com/index.html
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 ab.linux.com (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.16.1
Server Hostname: ab.linux.com
Server Port: 80
Document Path: /index.html
Document Length: 13 bytes
Concurrency Level: 200
Time taken for tests: 19.267 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 2490000 bytes
HTML transferred: 130000 bytes
Requests per second: 519.01 [#/sec] (mean)
Time per request: 385.349 [ms] (mean)
Time per request: 1.927 [ms] (mean, across all concurrent requests)
Transfer rate: 126.20 [Kbytes/sec] received
7.结论
nginx处理静态资源速度比tomcat快很多
8.影响性能的指标
1、网络
(1)网络的流量
(2)网络是否丢包
(3)这些会影响http的请求与调用
2、系统
(1)硬件有没有磁盘损坏,磁盘速率
(2)系统的负载、内存、系统稳定性
3、服务
(1)连接优化。请求优化
(2)根据业务形态做对应的服务设置
4、程序
(1)接口性能
(2)处理速度
(3)程序执行效率
5、数据库
系统性能优化
文件句柄,Linux一切皆文件,文件句柄可以理解为就是一个索引,文件句柄会随着我们进程的调用频繁增加,系统默认文件句柄是有限制的,不能让一个进程无限的调用,所以我们需要限制每个 进程和每个服务使用多大的文件句柄,文件句柄也是必须要调整的优化参数。
#查看文件句柄数 ulimit -n
#查看一个服务打开多少文件句柄 lsof -p pid
#查看一共打开多少文件句柄数 lsof -i | awk '{print $2}' |wc -l
1.设置文件句柄数
[root@web01 ~]# vim /etc/security/limits.conf
1.系统全局修改文件句柄
# * 代表所有用户,soft代表提醒,hard直接限制,nofile指定打开最大文件数量
* - nofile 65535
* soft nofile 65535
* hard nofile 65535
2.用户局部修改
root - nofile 65535
root soft nofile 65535
root hard nofile 65535
3.进程指定修改
#针对nginx进程,nginx自带配置,nginx.conf
worker_rlimit_nofile 65535;
2.系统层面优化
#调整内核参数:让time_wait状态端口可以重新使用
[root@web01 ~]# sysctl -a #查看所有内核参数
[root@web01 ~]# sysctl -p #查看我们手动配置的内核参数
[root@web01 ~]# vim /etc/sysctl.conf
#重用time_wait状态端口
[root@web01 ~]# sysctl -p
net.ipv4.tcp_tw_reuse = 1
代理服务优化
通常nginx作为代理服务,负责转发用户的请求,那么在转发的过程中建议开启HTTP长连接,用于减少握手次数,降低服务器损耗。
1.配置nginx代理开启长连接
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;
upstream tomcat {
server 127.0.0.1:8080;
keepalive 16; #开启长连接
}
server {
listen 80;
server_name daili.linux.com;
location /tomcat/ {
proxy_pass http://tomcat;
proxy_http_version 1.1; #指定http协议为1.1版本
proxy_set_header Connection ""; #清除“connection”头字段
include proxy_params; #调用优化配置
proxy_next_upstream error timeout http_500 http_502 http_503 http_504; #平滑过渡到另一台机器
}
}
2.代理到php服务保持长连接
upstream php_conn {
server 127.0.0.1:9000;
keepalive 16;
}
server {
listen 80;
server_name php.linux.com;
location /php/ {
root /code;
fastcgi_pass php_conn;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#开启长连接
fastcgi_keep_conn on;
#长连接超时时间
fastcgi_connect_timeout 60s;
include fastcgi_params;
}
}
静态资源优化
Nginx作为静态资源Web服务器,用于静态资源处理,传输非常的高效
静态资源指的是非WEB服务器端运行处理而生成的文件
静态资源类型 |
种类 |
浏览器渲染 |
HTML、CSS、JS |
图片文件 |
JPEG、GIF、PNG |
视频文件 |
FLV、Mp4、AVI |
其他文件 |
TXT、DOC、PDF、... |
1.静态资源缓存
浏览器缓存设置用于提高网站性能,尤其是新闻网站,图片一旦发布,改动的可能是非常小的,所以我们希望能否用户访问一次后,图片缓存在用户的浏览器长时间缓存。 浏览器是有自己的缓存机制,他是基于HTTP协议缓存机制来实现的,在HTTP协议中有很多头信息,那么实现浏览器的缓存就需要依赖特殊的头信息来与服务器进行特殊的验证,如Expires(http/1.0);Cache-control(http/1.1)。
ETag: "5e6864a0-c"
Last-Modified: Wed, 11 Mar 2020 04:10:08 GMT
Cache-Control: max-age=315360000
Expires: Wed, 02 Jan 2030 12:14:50 GMT
If-Modified-Since: Wed, 11 Mar 2020 04:10:08 GMT
If-None-Match: "5e6864a0-c"
1)浏览器读取缓存流程
1.浏览器请求服务器会先进行Expires、Cache-Control的检查,检查缓存是否过期,如果没有过期则直接从缓存文件中读取。
2.如果缓存过期首先检查是否存在etag,如果存在那么客户端会带着If-None-Match向web服务器请求,与etag值进行比对,如果值一致则走缓存,如果不一致则不走缓存。
3.如果etag不存在,则进行last-Modified检查,客户端会带着if-Modified-Since向web服务器请求,与last-Modified进行比对,如果值一致则走缓存,如果不一致则不走缓存。
Last-Modified:服务器上文件的最后修改时间
Etag:服务器上的文件标识
If-None-Match:浏览器上的文件标识
if-Modified-Since:浏览器保存的文件最后修改时间
Expires:本地缓存目录中,文件过期的时间
Cache-control:本地缓存目录中,文件过期的时间
2)缓存时间配置
#语法
#作用:添加Cache-Control Expires头
Syntax: expires [modified] time;
epoch | max | off;
Default: expires off;
Context: http, server, location, if in location
#配置静态资源缓存
[root@web01 static]# vim /etc/nginx/conf.d/huancun.conf
server {
listen 80;
server_name static.linux.com;
root /code/static;
location ~* \.(jpg|png|gif)$ {
expires 7d;
}
}
3)如果不想缓存
#1.开启无痕模式
#2.勾上disable_cache
#3.配置nginx
location ~* \.(css|js|html) {
add_header Cache-Control no-store;
add_header Pragma no-cache;
}
2.静态资源读取
1)文件高效读取配置语法
Syntax: sendfile on | off;
Default: sendfile off;
Context: http, server, location, if in location
2)高效传输(传输效率高)
#将多个数据带个包,一次推送,大文件适合打开此配置,必须要打开sendfile
Syntax: tcp_nopush on | off;
Default: tcp_nopush off;
Context: http, server, location
3)长连接传输(传输实时性高)
#来一个数据就推一个数据,需要开启keepalive
Syntax: tcp_nodelay on | off;
Default: tcpnodelay off;
Context: http, server, location
3.静态资源压缩
1)静态资源压缩语法
#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 3-5;
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
2)压缩实例
[root@web01 conf.d]# vim gzip.conf
server {
listen 80;
server_name gzip.linux.com;
root /code/static;
location ~* \.(jpg|png|gif)$ {
gzip on;
gzip_types image/gif image/jpeg image/png;
gzip_comp_level 5;
gzip_http_version 1.1;
}
location ~* \.(css|js|txt)$ {
gzip on;
gzip_types text/css application/javascript text/plain;
gzip_comp_level 5;
gzip_http_version 1.1;
}
}
[root@web01 conf.d]# ll /code/static/
total 1064
-rw-r--r-- 1 root root 409722 Mar 11 15:35 1.png
-rw-r--r-- 1 root root 670293 Mar 12 09:29 1.txt
-rw-r--r-- 1 root root 5 Mar 11 15:40 index.html
[root@web01 conf.d]#
4.防资源盗链
防盗链,就是指资源被其他网站恶意盗用
基础防盗链设置思路:主要是针对客户端请求过程中所携带的一些Header信息来验证请求的合法性,比如客户端在请求的过程中都会携带referer信息。优点是规则简单,配置和使用都很方便,缺点是防盗链所依赖的Referer验证信息是可以伪造的,所以通过referer信息防盗链并非100%可靠,但是他能够限制大部分的盗链情况。
1)防盗链配置语法
Syntax: valid_referers none | blocked | server_name | string ...;
Default: -;
Context: server, location
#none: referer来源头部为空的情况
#blocked: referer来源头部不为空,这些都不以http://或者https://开头
#server_name: 来源头部信息包含当前域名,可以正则匹配
valid_referers none blocked www.linux.com server_names *.example.com example.* ~\.google\.;
if ($invalid_referer) {
return 403;
}
2)配置被盗连的机器
#1.配置nginx
[root@web02 conf.d]# vim beidl.conf
server {
listen 80;
server_name beidl.linux.com;
location / {
root /code;
index index.html;
}
}
#2.上传两张图片
[root@web02 code]# ll
total 123748
-rw-r--r-- 1 www www 657306 Mar 21 2019 1.jpg
-rw-r--r-- 1 www www 475653 Jul 17 2019 2.jpg
#3.重启nginx
3)配置盗链的机器
#1.配置nginx
[root@web01 conf.d]# vim dl.conf
server {
listen 80;
server_name dl.linux.com;
location / {
root /code/dl;
index index.html;
}
}
#2.配置盗链的页面
[root@web01 conf.d]# vim /code/dl/dl.html
<html>
<head>
<meta charset="utf-8">
<title>dl.com</title>
</head>
<body style="background-color:pink;">
<img src="http://beidl.linux.com/1.jpg"/>
</body>
</html>
#3.配置hosts
4)配置防盗链
[root@web02 conf.d]# vim beidl.conf
server {
listen 80;
server_name beidl.linux.com;
root /code;
location / {
index index.html;
}
location ~* \.(jpg|png|gif)$ {
valid_referers none blocked beidl.linux.com;
if ($invalid_referer) {
return 500; #直接返回错误
#rewrite (.*) /2.jpg; #跳转到另一张图片
}
}
}
5)允许匹配多个域名访问
server {
listen 80;
server_name beidl.linux.com;
root /code;
location / {
index index.html;
}
location ~* \.(jpg|png|gif)$ {
valid_referers none blocked beidl.linux.com server_name *.example.com;
if ($invalid_referer) {
return 500;
#rewrite (.*) /2.jpg break;
}
}
}
6)伪造refere信息访问
[root@web01 conf.d]# curl -e "https://www.example.com" -I beidl.linux.com/1.jpg
HTTP/1.1 200 OK
Server: nginx/1.16.1
Date: Thu, 12 Mar 2020 03:10:32 GMT
Content-Type: image/jpeg
Content-Length: 657306
Last-Modified: Thu, 21 Mar 2019 05:54:55 GMT
Connection: keep-alive
ETag: "5c93272f-a079a"
Accept-Ranges: bytes
[root@web01 conf.d]# curl -e "https://www.google.com" -I beidl.linux.com/1.jpg
HTTP/1.1 500 Internal Server Error
Server: nginx/1.16.1
Date: Thu, 12 Mar 2020 03:10:41 GMT
Content-Type: text/html
Content-Length: 177
Connection: close
允许跨域访问
什么是跨域访问,当我们通过浏览器访问a网站时,同事会利用到ajax或其他方式,同时也请求b网站,这样的话就出现了请求一个页面,使用了两个域名,这种方式对浏览器来说默认是禁止的。
1.配置被跨域的网站
#1.配置nginx
[root@web02 conf.d]# vim beikuayu.conf
server {
listen 80;
server_name beikuayu.linux.com;
location / {
root /code;
index index.html;
}
}
#2.重启nginx
#3.配置页面
[root@web02 conf.d]# echo "beikuayuwangzhan" > /code/index.html
2.配置跨域网站
#1.配置nginx
[root@web01 conf.d]# vim kuayu.conf
server {
listen 80;
server_name kuayu.linux.com;
location / {
root /code/kuayu;
index index.html;
}
}
#2.配置页面
[root@web01 conf.d]# mkdir /code/kuayu
<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://beikuayu.linux.com",
success: function(data) {
alert("sucess 卧槽 卧槽 卧槽 成功了!!!");
},
error: function() {
alert("fail!!,跨不过去啊,不让进去啊,只能蹭蹭!");
}
});
});
</script>
<body>
<h1>测试跨域访问</h1>
</body>
</html>
#3.配置hosts
#4.重启nginx
3.配置允许跨域访问
[root@web02 conf.d]# vim beikuayu.conf
server {
listen 80;
server_name beikuayu.linux.com;
root /code;
index index.html;
location ~* \.html$ {
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,获得更好的性能。
1.查看CPU状态
[root@web02 ~]# lscpu
Thread(s) per core: 1
CPU(s): 4
On-line CPU(s) list: 0-3
NUMA node0 CPU(s): 0-3
#一个物理CPU上面有四个内核,分别是 0 1 2 3
2.把worker进程绑定不同核心
#nginx worker进程数量,一定要与核心数保持一致
# 第一种绑定组合方式(不推荐)
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.配置cpu亲和后
[root@web02 ~]# vim /etc/nginx/nginx.conf
user www;
worker_processes auto;
worker_cpu_affinity auto;
[root@web02 ~]# ps -eo pid,args,psr|grep [n]ginx
7063 nginx: master process /usr/ 3
7065 nginx: worker process 0
7066 nginx: worker process 1
7067 nginx: worker process 2
7068 nginx: worker process 3
[root@web02 ~]#
nginx通用优化配置
[root@nginx ~]# cat nginx.conf
user www; #nginx用户
worker_processes auto; #自动根据CPU核心数启动worker数量
worker_cpu_affinity auto; #开启亲和性
error_log /var/log/nginx/error.log warn; #错误日志
pid /run/nginx.pid; #指定pid文件
worker_rlimit_nofile 35535; #nginx最大打开文件句柄数
events {
use epoll; #使用epoll网络模型
worker_connections 10240; #每个worker处理的连接数
}
http {
include mime.types; #nginx可是别的文件类型
default_type application/octet-stream; #nginx不认识的文件类型就默认下载
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"';
#定义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; #高效传输
tcp_nodelay on; #实时传输
keepalive_timeout 65; #长连接
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字节才开始压缩
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; #虚拟主机配置文件
}
通用纯净版
user nginx;
worker_processes auto;
worker_cpu_affinity auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
worker_rlimit_nofile 35535;
events {
use epoll;
worker_connections 10240;
}
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"';
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 json_access;
server_tokens off;
client_max_body_size 200m;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
gzip on;
gzip_disable "MSIE [1-6]\.";
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_buffers 16 8k;
gzip_min_length 1024;
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安全优化总结
1、CPU亲和、worker进程数、调整nginx进程打开的文件句柄数
2、使用Epool网络模型、调整每个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.ini配置文件优化
#;;;;;;;;;;;;;;;;;
# Error 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 # 每个脚本执行最大内存
[Session] #会话共享
session.save_handler = redis
session.save_path = "tcp://172.16.1.51:6379"
#php禁止危险函数执行(取决于实际情况,需要和开发沟通)
disable_functions = chown,chmod,pfsockopen,phpinfo
2.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,pfsockopen,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,fsocket,fsockopen
3.php-fpm进程的配置
[root@web01 ~]# 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
[root@web01 ~]# 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不限制
#php进程管理方式,静态管理配置多少就是多少,动态管理
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 #记录至该文件中
[21-Nov-2013 14:30:38] [pool www] pid 11877
script_filename = /usr/local/lnmp/nginx/html/www.quancha.cn/www/fyzb.php
[0xb70fb88c] file_get_contents() /usr/local/lnmp/nginx/html/www.quancha.cn/www/fyzb.php:2
4.开启php状态监控
#配置开启监控模块
[root@web01 ~]# vim /etc/php-fpm.d/www.conf
pm.status_path = /status #开启php的状态页面
#配置nginx将页面交给php处理
[root@web01 ~]# vim /etc/nginx/conf.d/php.conf
server {
listen 80;
server_name test.php.com;
root /code;
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 {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
5.状态页面参数详解
pool: dnf #池名称
process manager: dynamic #进程管理方式
start time: 12/Mar/2020:16:33:46 +0800 #服务启动时间
start since: 163 #启动了多少秒
accepted conn: 2 #连接数
listen queue: 0 #等待队列
max listen queue: 0 #等待队列最大值
listen queue len: 128 #等待队列长度
idle processes: 4 #空闲的php进程
active processes: 1 #活跃的php进程
total processes: 5 #php一共多少个进程
max active processes: 1 #最大的活跃进程
max children reached: 0 #进程最大数量限制的次数
slow requests: 0 #慢请求
6.当服务器配置是4核32G时
[root@nginx ~]# cat /etc/php-fpm.d/www.conf
[global]
pid = /var/run/php-fpm.pid
error_log = /var/log/php-fpm.log
log_level = warning
rlimit_files = 655350
events.mechanism = epoll
[www]
user = nginx
group = nginx
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 512
pm.start_servers = 32
pm.min_spare_servers = 32
pm.max_spare_servers = 64
pm.process_idle_timeout = 15s;
pm.max_requests = 2048
pm.status_path = /phpfpm_status
#php-www模块错误日志
php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/php/php-www.log
php_admin_flag[log_errors] = on
#php慢查询日志
request_slowlog_timeout = 5s
slowlog = /var/log/php-slow.log
优化总结
nginx
硬件 nginx做代理比较消耗CPU、内存,nginx做静态资源管理比较消耗磁盘和IO;
网络 带宽,传输速率,是否丢包
系统 调整文件描述符,time_wait重用
应用 keepalive长连接
服务 nginx管理静态资源 浏览器缓存、文件高效传输、压缩、防盗链、跨域访问、CPU亲和
nginx做安全 nginx+lua 实现 waf 防火墙
php
php.ini 访问错误日志,上传文件大小调整、session共享配置
php-fpm 监听地址,动态调节php进程,启动日志
php状态模块
php慢查询