當(dāng)我需要進行性能優(yōu)化時,說明我們服務(wù)器無法滿足日益增長的業(yè)務(wù)。性能優(yōu)化是一個比較大的課題,需要從以下幾個方面進行探討
- 當(dāng)前系統(tǒng)結(jié)構(gòu)瓶頸
- 了解業(yè)務(wù)模式
- 性能與安全
當(dāng)前系統(tǒng)結(jié)構(gòu)瓶頸
首先需要了解的是當(dāng)前系統(tǒng)瓶頸,用的是什么,跑的是什么業(yè)務(wù)。里面的服務(wù)是什么樣子,每個服務(wù)最大支持多少并發(fā)。比如針對nginx而言,我們處理靜態(tài)資源效率最高的瓶頸是多大?能支持多少qps訪問請求?怎么得出系統(tǒng)當(dāng)前的結(jié)構(gòu)瓶頸?
可以通過查看當(dāng)前cpu負荷,內(nèi)存使用率,進程使用率來做簡單判斷。還可以通過操作系統(tǒng)的一些工具來判斷當(dāng)前系統(tǒng)性能瓶頸,如分析對應(yīng)的日志,查看請求數(shù)量。也可以通過nginx http_stub_status_module模塊來查看對應(yīng)的連接數(shù),總握手次數(shù),總請求數(shù)。也可以對線上進行壓力測試,來了解當(dāng)前的系統(tǒng)能性能,并發(fā)數(shù),做好性能評估。
了解業(yè)務(wù)模式
雖然我們是在做性能優(yōu)化,但還是要熟悉業(yè)務(wù),最終目的都是為業(yè)務(wù)服務(wù)的。我們要了解每一個接口業(yè)務(wù)類型是什么樣的業(yè)務(wù),比如電子商務(wù)搶購模式,這種情況平時流量會很小,但是到了搶購時間,流量一下子就會猛漲。也要了解系統(tǒng)層級結(jié)構(gòu),每一層在中間層做的是代理還是動靜分離,還是后臺進行直接服務(wù)。需要我們對業(yè)務(wù)接入層和系統(tǒng)層次要有一個梳理
性能與安全
性能與安全也是一個需要考慮的因素,往往大家注重性能忽略安全或注重安全又忽略性能。比如說我們在設(shè)計防火墻時,如果規(guī)則過于全面肯定會對性能方面有影響。如果對性能過于注重在安全方面肯定會留下很大隱患。所以大家要評估好兩者的關(guān)系,把握好兩者的孰重孰輕,以及整體的相關(guān)性。權(quán)衡好對應(yīng)的點。
1.ab接口壓力測試工具
ab是Apache超文本傳輸協(xié)議(HTTP)的性能測試工具。其設(shè)計意圖是描繪當(dāng)前所安裝的Apache的執(zhí)行性能,主要是顯示你安裝的Apache每秒可以處理多少個請求。
查看更多ab使用詳情傳送門
2.系統(tǒng)與nginx性能優(yōu)化
大家對相關(guān)的系統(tǒng)瓶頸及現(xiàn)狀有了一定的了解之后,就可以根據(jù)影響性能方面做一個全體的評估和優(yōu)化。
- 網(wǎng)絡(luò)(網(wǎng)絡(luò)流量、是否有丟包,網(wǎng)絡(luò)的穩(wěn)定性都會影響用戶請求)
- 系統(tǒng)(系統(tǒng)負載、飽和、內(nèi)存使用率、系統(tǒng)的穩(wěn)定性、硬件磁盤是否有損壞)
- 服務(wù)(連接優(yōu)化、內(nèi)核性能優(yōu)化、http服務(wù)請求優(yōu)化都可以在nginx中根據(jù)業(yè)務(wù)來進行設(shè)置)
- 程序(接口性能、處理請求速度、每個程序的執(zhí)行效率)
- 數(shù)據(jù)庫、底層服務(wù)
上面列舉出來每一級都會有關(guān)聯(lián),也會影響整體性能,這里主要關(guān)注的是nginx服務(wù)這一層。
3.文件句柄
在linux/unix操作系統(tǒng)中一切皆文件,我們的設(shè)備是文件,文件是文件,文件夾也是文件。當(dāng)我們用戶每發(fā)起一次請求,就會產(chǎn)生一個文件句柄。文件句柄可以簡單的理解為文件句柄就是一個索引。文件句柄就會隨著請求量的增多,進程調(diào)用頻繁增加,那么產(chǎn)生的文件句柄也就會越多。
系統(tǒng)默認對文件句柄是有限制的,不可能會讓一個進程無限制的調(diào)用句柄。因為系統(tǒng)資源是有限的,所以我們需要限制每一個服務(wù)能夠使用多大的文件句柄。操作系統(tǒng)默認使用的文件句柄是1024個句柄。
設(shè)置方式
- 系統(tǒng)全局性修改
- 用戶局部性修改
- 進程局部性修改
系統(tǒng)全局性修該和用戶局部性修改
vim /etc/security/limits.conf
在文件最下面找到
#* soft core 0
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#@student - maxlogins 4
root soft nofile 65535 #root用戶
root hard nofile 65535
* soft nofile 65535 #所有用戶
* hard nofile 65535
可以看到root和*,root代表是root用戶,*代表的是所有用戶,后面的數(shù)字就是文件句柄大小。大家可以根據(jù)個人業(yè)務(wù)來進行設(shè)置。
進程局部性修改
vim /etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_rlimit_nofile 65535; #進程限制
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'"$args" "$request_uri"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
worker_rlimit_nofile 是在進程上面進行限制。
4.cpu的親和配置
cpu的親和能夠使nginx對于不同的work工作進程綁定到不同的cpu上面去。就能夠減少在work間不斷切換cpu,把進程通常不會在處理器之間頻繁遷移,進程遷移的頻率小,來減少性能損耗。nginx 親和配置
查看當(dāng)前cpu
cat /proc/cpuinfo|grep "physical id"|sort |uniq|wc -l
查看cpu是幾核的
cat /proc/cpuinfo|grep "cpu cores"|uniq
查看cpu使用率
top 回車后按 1
配置worker_processes
vim /etc/nginx/nginx.conf
將剛才查看到自己cpu * cpu核心就是worker_processes
worker_processes 1; #小菜的配置很低所以都是1核
cpu親和配置
假如小菜的配置是2cpu,每個cpu是8核。配置如下
worker_processes 16;
worker_cpu_affinity 1010101010101010 0101010101010101;
配置完成后可以通過下面命令查看nginx進程配置在哪個核上
ps -eo pid,args,psr |grep [n]ginx
在nginx 1.9版本之后,就幫我們自動綁定了cpu;
worker_cpu_affinity auto;
5.nginx通用配置優(yōu)化
vim /etc/nginx/nginx.conf
#將nginx進程設(shè)置為普通用戶,為了安全考慮
user nginx;
#上面配置講過了
worker_processes 1;
worker_cpu_affinity auto;
#日志配置成warn
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker-rlimit-nofile 25535; #文件句柄
events {
use epoll; #事件模型
worker_connections 1024; #nginx 請求連接數(shù),對于1核nginx能夠處理1024 如果是多核可以將連接數(shù)調(diào)高 worker_processes * 1024
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
charset utf-8; #設(shè)置字符集
#設(shè)置日志輸出格式,根據(jù)自己的情況設(shè)置
log_format main '$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'"$args" "$request_uri"';
access_log /var/log/nginx/access.log main;
sendfile on; #對靜態(tài)資源的處理比較有效
#tcp_nopush on; #如果做靜態(tài)資源服務(wù)器可以打開
#tcp_nodeny on; #當(dāng)nginx做動態(tài)的服務(wù)時可以選擇打開
keepalive_timeout 65;
########
#Gzip module
gzip on; #文件壓縮默認可以打開
gzip_disable "MSIE [1-6]\."; #對于有些瀏覽器不能識別壓縮,需要過濾如ie6
gzip_http_version 1.1;
include /etc/nginx/conf.d/*.conf;
}
