性能优化概述
性能优化概述
1、了解每个服务
2、需要了解业务模式
3、最后我们需要考虑性能与安全
压力测试工具
[root@web01 conf.d]# yum install httpd-tools -y #配置nginx [root@lb01 conf.d]# cat try.conf server { listen 80; server_name try.haoda.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使用的静态页面 [root@lb01 conf.d]# echo "nginx ab" > /code/ad.html #配置tomcat使用的静态页面 [root@web02 ~]# wget http://mirrors.hust.edu.cn/apache/tomcat/tomcat-9/v9.0.16/bin/apache-tomcat-9.0.16.tar.gz [root@web02 ~]# tar xf apache-tomcat-9.0.16.tar.gz [root@web02 ~]# cd /usr/share/tomcat/webapps/root [root@web02 root]# echo "tomcat aaaaa" > tomcat.html #压测工具测试nginx处理静态资源 [root@lb01 conf.d]# ab -n 10000 -c 200 http://try.haoda.com/ad.html server software: nginx/1.14.2 server hostname: try.haoda.com server port: 80 document path: /ad.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@lb01 conf.d]# ab -n 10000 -c 200 http://try.haoda.com/tomcat.html server software: nginx/1.14.2 server hostname: try.haoda.com server port: 80 document path: /tomcat.html document length: 13 bytes concurrency level: 200 time taken for tests: 4.956 seconds complete requests: 10000 failed requests: 0 write errors: 0 total transferred: 2510000 bytes html transferred: 130000 bytes requests per second: 2017.78 [#/sec] (mean) time per request: 99.119 [ms] (mean) time per request: 0.496 [ms] (mean, across all concurrent requests) transfer rate: 494.59 [kbytes/sec] received
了解影响性能指标
1、网络 (1)网络的流量 (2)网络是否丢包 (3)这些会影响http的请求与调用 2、系统 (1)硬件有没有磁盘损坏,磁盘速率 (2)系统的负载、内存、系统稳定性 3、服务 (1)连接优化。请求优化 (2)根据业务形态做对应的服务设置 4、程序 (1)接口性能 (2)处理速度 (3)程序执行效率 5、数据库 #每个服务与服务之间都或多或少有一些关联,我们需要将整个架构进行分层,找到对应系统或服务的短板,然后进行优化
系统性能优化
文件句柄,linux一切皆文件,文件句柄可以理解为就是一个索引,文件句柄会随着我们进程的调用频繁增加,系统默认文件句柄是有限制的,不能让一个进程无限的调用,所以我们需要限制每个 进程和每个服务使用多大的文件句柄,文件句柄也是必须要调整的优化参数。
文件句柄的设置方式:
1、系统全局性修改。
2、用户局部性修改。
3、进程局部性修改。
[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 = 1 [root@web01 root]# sysctl -p #可以查看我们添加的内核参数 [root@web01 root]# sysctl -a #可以查看所有内核参数
在高并发短连接的tcp服务器上,当服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量socket处于time_wait状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上。 我来解释下这个场景。主动正常关闭tcp连接,都会出现timewait。
为什么我们要关注这个高并发短连接呢?有两个方面需要注意: 1. 高并发可以让服务器在短时间范围内同时占用大量端口,而端口有个0~65535的范围,并不是很多,刨除系统和其他服务要用的,剩下的就更少了。 2. 在这个场景中,短连接表示“业务处理+传输数据的时间 远远小于 timewait超时的时间”的连接。
这里有个相对长短的概念,比如取一个web页面,1秒钟的http短连接处理完业务,在关闭连接之后,这个业务用过的端口会停留在timewait状态几分钟,而这几分钟,其他http请求来临的时候是无法占用此端口的(占着茅坑不拉翔)。单用这个业务计算服务器的利用率会发现,服务器干正经事的时间和端口(资源)被挂着无法被使用的时间的比例是 1:几百,服务器资源严重浪费。(说个题外话,从这个意义出发来考虑服务器性能调优的话,长连接业务的服务就不需要考虑timewait状态。同时,假如你对服务器业务场景非常熟悉,你会发现,在实际业务场景中,一般长连接对应的业务的并发量并不会很高。
代理服务优化
配置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_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; ... } }
keepalive_requests设置通过一个keepalive连接提供的最大请求数,在发出最大请求数后,将关闭连接。
syntax: keepalive_requests number; default: keepalive_requests 100; context: upstream
keepalive_timeout设置超时,再次期间与代理服务器的空闲keepalive连接将保持打开状态。
syntax: keepalive_timeout timeout; default: keepalive_timeout 60s; context: upstream #该指令出现在1.15.3版中
注意:
1.scgi和uwsgi协议没有保持连接的概念。
2.但无论是proxy、fastcgi、uwsgi协议都有cache缓存的功能,开启后可加速网站访问的效率。(取决硬件)
静态资源缓存
浏览器无缓存
浏览器有缓存
浏览器过期校验机制
浏览器if-none-match "9-1550193224000" 询问 web服务器 etag "9-1550193224000" 浏览器认为只是缓存过期,内容并没有修改,所以协商后还是304
浏览器if-modified-since tue, 29 jan 2019 02:29:51 gmt 询问 web服务器 last-modified: tue, 29 jan 2019 02:29:51 gmt 浏览器认为只是缓存过期,内容并没有修改,所以协商后还是304
配置静态资源缓存场景
server { listen 80; server_name static.haoda.com; location ~ .*\.(jpg|gif|png)$ { expires 7d; } location ~ .*\.(js|css)$ { expires 30d; } }
取消缓存
location ~ \.*(png|jpg|gif|jpeg)$ { expires 30d; add_header cache-control no-store; add_header pragma no-cache; } }
静态资源压缩
文件读取高效sendfile,如下图
syntax: sendfile on | off; default: sendfile off; context: http, server, location, if in location
传统读取文件方式 与 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
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
针对图片
location ~* .*\.(jpg|gif|png)$ { root /code/images; gzip on; gzip_http_version 1.1; gzip_comp_level 2; #极致为9,压缩的级别 gzip_types image/jpeg image/gif image/png; #文件格式 }
针对txt
[root@nginx conf.d]# cat static_server.conf server { listen 80; server_name static.oldboy.com; sendfile on; 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; } }
防止资源盗链
防盗链,指的是防止资源被其他网站恶意盗用。
基础防盗链设置思路:主要是针对客户端请求过程中所携带的一些header信息来验证请求的合法性,比如客户端在请求的过程中都会携带referer信息。优点是规则简单,配置和使用都很方便,缺点是防盗链所依赖的referer验证信息是可以伪造的,所以通过referer信息防盗链并非100%可靠,但是他能够限制大部分的盗链情况。
syntax: valid_referers none | blocked | server_name | string ...; default: -; context: server, location #none: referer来源头部为空的情况 #blocked: referer来源头部不为空,这些都不以http://或者https://开头 #server_name: 来源头部信息包含当前域名,可以正则匹配
syntax: valid_referers none | blocked | server_name | string ...; default: -; context: server, location #none: referer来源头部为空的情况 #blocked: referer来源头部不为空,这些都不以http://或者https://开头 #server_name: 来源头部信息包含当前域名,可以正则匹配
5.4.1 在盗链服务器上准备html文件,偷取我的图片
<html> <head> <meta charset="utf-8"> <title>haoda.com</title> </head> <body style="background-color:black;"> <img src="http://39.104.205.72/picture/niu.jpg"/> </body> </html>
5.4.2 访问页面查看
5.4.3 服务器上配置防盗链
location ~ .*\.(jpg|png|gif) { root /data; valid_referers none blocked 39.104.205.72; if ( $invalid_referer ) { return 403; } }
以上配置含义表示,所有来自39.104.205.72都可以访问到当前站点的图片,如果来源域名不在这个列表中,那么$invalid_referer等于1,在if语句中返回一个403个客户,这样用户便会看到一个403的页面
5.4.4 如果不使用return而是用rewrite,那么盗链图片会返回一个pei.jpg给用户
location ~ .*\.(jpg|png|gif) { root /data; valid_referers none blocked 39.104.205.72; if ( $invalid_referer ) { rewrite ^(.*)$ /picture/pei.jpg break; } }
5.4.5 如果希望某些网站可以盗链
location ~ .*\.(jpg|png|gif) { root /data; valid_referers none blocked 39.104.205.72 server_name ~\.google\. ~\.baidu\.; if ( $invalid_referer ) { return 403; } }
当然这种防护并不能百分百保证资源不被盗链,因为我们可以通过命令来修改来源的refer信息。
[root@lb01 conf.d]# curl -e "http://www.baidu.com" -i http://39.104.205.72/picture/niu.jpg [root@lb01 conf.d]# curl -e "http://39.104.205.72" -i http://39.104.205.72/picture/niu.jpg
生产实践
1.配置网站
[root@web02 conf.d]# cat static.conf server { listen 80; server_name static.oldboy.com; root /code; location / { index index.html; } }
2.上传2张图片
一张是可以被盗链的图片
一张是广告位的图片
重启服务器
[root@web02 code]# systemctl restart nginx
3.配置盗链服务器
[root@web01 conf.d]# cat try.conf server { server_name dl.oldboy.com; listen 80; root /code; location / { index index.html; } }
配置盗链页面
[root@web01 code]# cat /code/tt.html <html> <head> <meta charset="utf-8"> <title>oldboyedu.com</title> </head> <body style="background-color:red;"> <img src="http://static.oldboy.com/smg.jpg"/> #根据情况修改你的服务器地址 </body> </html>
4.web02添加防盗链操作
location ~* \.(gif|jpg|png|bmp)$ { valid_referers none blocked *.xuliangwei.com server_ names ~\.google\.; if ($invalid_referer) { return 403; #可以选择直接返回403 rewrite ^(.*)$ /ggw.png break; #也可以选择返回一张水印的图片,给公司做广告 }
允许跨域访问
1.配置a网站
[root@nginx ~]# cat /code/http_origin.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://naonao.lq.com/1.jpg", success: function(data) { alert("sucess!!!"); }, error: function() { alert("fail!!,请刷新再试!"); } }); }); </script> <body> <h1>测试跨域访问</h1> </body> </html>
2.配置b网站
3.通过浏览器测试跨域访问
4.在b网站上允许a网站跨域访问
server { server_name naonao.lq.com; listen 80; root /code; location / { index index.html; } location ~* \.(gif|jpg|png|bmp)$ { add_header access-control-allow-origin *; add_header access-control-allow-methods get,post,put,delete,options; } }
cpu亲和
1.查看当前cpu物理状态
[root@nginx ~]# lscpu |grep "cpu(s)" cpu(s): 24 #总的核心数 on-line cpu(s) list: 0-23 每个物理cpu使用的是那些核心(代表2颗物理cpu,) 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 #本次演示服务器为 两颗物理cpu,每颗物理cpu12个核心, 总共有24个核心
修改nginx启动的work进程为自动
worker_processes auto; worker_cpu_affinity auto; [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
不推荐调整的方式 # 第一种绑定组合方式 worker_processes 24; worker_cpu_affinity 000000000001 000000000010 000000000100 000000001000 000000010000 000000100000 000001000000 000010000000 000100000000 001000000000 010000000000 10000000000; # 第二种方式(使用较少) worker_processes 2; worker_cpu_affinity 101010101010 010101010101;
nginx通用配置 nginx代理相关配置 nginx fastcgi
[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"'; 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]\."; 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 applicati on/xml+rss text/javascript image/jpeg; # 虚拟主机 include /etc/nginx/conf.d/*.conf; }
nginx安全与优化总结
1.cpu亲和、worker进程数、调整每个worker进程打开的文件数
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程序配置管理文件/etc/php.ini,主要调整日志、文件上传、禁止危险函数、关闭版本号显示、等
#;;;;;;;;;;;;;;;;; error logging ; #错误日志设置 #;;;;;;;;;;;;;;;;; expose_php = off # 关闭php版本信息 display_error = off # 屏幕不显示错误日志 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" #有密码写?auth= https://blog.csdn.net/unixtech/article/details/53761832 #php禁止危险函数执行(取决于实际情况,需要和开发沟通) disable_functions = chown,chmod,pfsockopen,phpinfo
2.php-fpm进程管理配置文件/etc/php-fpm.conf
#第一部分,fpm配置 ;include=etc/fpm.d/*.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事件模型处理请求 #第三部分,进程池定义 [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 #动态调节php-fpm的进程数 pm.max_children = 512 #最大启动的php-fpm进程数 pm.start_servers = 32 #初始启动的php-fpm进程数 pm.min_spare_servers = 32 #最少的空闲php-fpm进程数 pm.max_spare_servers = 64 #最大的空闲php-fpm进程数 pm.max_requests = 1500 #每一个进程能响应的请求数 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
3.php 状态页面 pm.status_path = /phpfpm_status #开启php的状态页面
配置文件
[root@nginx ~]# curl http://127.0.0.1/phpfpm_status pool: www #fpm池名称,大多数为www process manager: dynamic #动态管理phpfpm进程 start time: 05/jul/2016 #启动时间,如果重启会发生变化 start since: 409 #php-fpm运行时间 accepted conn: 22 #当前池接受的连接数 listen queue: 0 #请求等待队列,如果这个值不为0,那么需要增加fpm的进程数量 max listen queue: 0 #请求等待队列最高的数量 listen queue len: 128 #请求等待队列的长度 idle processes: 4 #php-fpm空闲的进程数量 active processes: 1 #php-fpm活跃的进程数量 total processes: 5 #php-fpm总的进程数量 max active processes: 2 #php-fpm最大活跃的进程数量(fpm启动开始计算) max children reached: 0 #进程最大数量限制的次数,如果数量不为0,则说明phpfpm最大进程数量过小,可以适当调整。
4.php-fpm配置文件 4核16g、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
硬件层面 代理比较的消耗cpu、内存、 静态比较消耗磁盘io、 网络层面 网络带宽大小、传输速率、是否有丢包、 系统层面 调整文件描述。 timewait重用 应用层面 nginx作为代理 keepalive 长连接 服务层面 nginx作为静态 浏览器缓存、文件传输、压缩、防盗链、跨域访问、cpu亲和 nginx作为缓存 proxy_cache fastcgi_cache uwsgi_cache nginx作为安全 nginx+lua实现waf防火墙
php
php.ini 错误日志记录、文件大小的调整、session会话共享的配置、禁止不必要的函数(与开发协商) php-fpm 监听地址、进程的动态调节、日志开启。 php状态 php自身监控的状态信息 php慢查询 什么时间、什么进程、运行什么文件、哪个函数、第几行达到了超时时间
上一篇: 操作系统原理之文件系统(第五章)