Nginx(全)
文章目錄
- 一、Nginx
- 1、概念
- 1、工作原理
- 2、Nginx模塊
- Nginx rewrite概述
- 3、Nginx 的進(jìn)程模型
- 二、Nginx優(yōu)點(diǎn)
- 1、優(yōu)點(diǎn)
- 2、正向代理和反向代理的區(qū)別
- 1)正向代理
- 2)反向代理
- 3、Nginx如何處理HTTP請求的?
- 1)多進(jìn)程機(jī)制(單線程)
- 2)異步非阻塞機(jī)制
- 4、Nginx的master和worker
- 5、Nginx 常用命令
- 6、Nginx狀態(tài)碼
- 1)3開頭
- 2)4開頭
- 3)5開頭
- 7、Nginx 壓縮
- 8、Nginx 和 Apache、Tomcat 之間的不同點(diǎn)
- Nginx和Apache區(qū)別:
- 9、Nginx動靜態(tài)資源分離
- 10、ngx_http_upstream_module
- 11、限流了解嗎,怎么限流的?
- 1、控制速率
- 2、控制并發(fā)連接數(shù)
- 12、nginx重定向,重寫URL
- 13、nginx是如何實現(xiàn)高并發(fā)的?
- 14、使用nginx代理后,獲取用戶真實ip
- 三、Nginx的優(yōu)化
- 1、隱藏版本號
- 2、修改用戶與組
- 3、配置網(wǎng)頁緩存時間
- 4、日志分割
- 5、設(shè)置連接超時
- 6、更改進(jìn)程數(shù)
- 7、配置網(wǎng)頁壓縮
- 8、配置防盜鏈
- 9、FPM參數(shù)優(yōu)化
- 10、內(nèi)核優(yōu)化
- 四、Nginx負(fù)載均衡
- 1、四層和七層
- 2、熱備
- 3、負(fù)載均衡策略(算法)
- 4、負(fù)載均衡狀態(tài)
- 六、FastCG、php-fpm
- 1、Nginx+FastCGI運(yùn)行原理
- 2、缺省安裝的Nginx+php-fpm環(huán)境
- 3、已知nginx和php-fpm安裝在同一臺服務(wù)器上,nginx連接php-fpm有兩種方式:一種是類似127.0.0.1:9000的TCP socket,另一種是類似/tmp/php-fpm.sock的Unix domain socket,請問如何選擇?需要注意什么?
一、Nginx
1、概念
Nginx是一個 Web 服務(wù)器和反向代理服務(wù)器用于 HTTP、HTTPS、SMTP、POP3 和 IMAP 協(xié)議。因它的穩(wěn)定性、豐富的功能集、示例配置文件和低系統(tǒng)資源的消耗而聞名
1、工作原理
Nginx 由內(nèi)核和模塊組成。
Nginx 本身做的工作實際很少,當(dāng)它接到一個 HTTP 請求時, 它僅僅是通過查找配置文件將此次請求映射到一個 location 模塊,而此 location 中所配 置的各個指令則會啟動不同的模塊去完成工作,因此模塊可以看做 Nginx 真正的勞動工作者。
通常一個 location 中的指令會涉及一個 handler 模塊和多個 filter 模塊(當(dāng)然,多個 location 可以復(fù)用同一個模塊)。handler 模塊負(fù)責(zé)處理請求,完成響應(yīng)內(nèi)容的生成,而 filter 模塊對響應(yīng)內(nèi)容進(jìn)行處理。 用戶根據(jù)自己的需要所開發(fā)的模塊都屬于第三方模塊。正是有了這么多模塊的支撐, Nginx 的功能才會如此強(qiáng)大。
2、Nginx模塊
https://www.w3cschool.cn/nginx/
vim /etc/nginx/conf.d/default.conf
vim /usr/local/nginx/conf/nginx.conf
nginx模塊分為兩種,官方和第三方,我們通過命令 nginx -V 查看 nginx已經(jīng)安裝的模塊!
如果需要添加某個模塊,需要將工作目錄切換至nginx的源碼包中,執(zhí)行“nginx -V”命令查看之前配置時的選項進(jìn)行復(fù)制,然后增加需要添加的模塊配置項,進(jìn)行配置并編譯,將新生成的nginx命令覆蓋掉原有的nginx命令,然后重載nginx服務(wù),即可實現(xiàn)在線添加模塊。
[root@localhost ~]# nginx -V
nginx version: nginx/1.15.9 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module| ngx_http_access_module | 四層基于IP的訪問控制,可以通過匹配客戶端源IP地址進(jìn)行限制 |
| ngx_http_auth_basic_module | 狀態(tài)頁,使用basic機(jī)制進(jìn)行用戶認(rèn)證,在編譯安裝nginx的時候需要添加編譯參數(shù)–withhttp_stub_status_module,否則配置完成之后監(jiān)測會是提示語法錯誤 |
| ngx_http_stub_status_module | 狀態(tài)統(tǒng)計模塊 |
| ngx_http_gzip_module | 文件的壓縮功能 |
| ngx_http_gzip_static_module | 靜態(tài)壓縮模塊 |
| ngx_http_ssl_module | nginx 的https 功能 |
| ngx_http_rewrite_module | 實現(xiàn)URL地址重寫,URL看起來更規(guī)范、合理 |
| ngx_http_referer_module | 防盜鏈功能,基于訪問安全考慮 |
| ngx_http_proxy_module | 將客戶端的請求以http協(xié)議轉(zhuǎn)發(fā)至指定服務(wù)器進(jìn)行處理 |
| ngx_stream_proxy_module | tcp負(fù)載,將客戶端的請求以tcp協(xié)議轉(zhuǎn)發(fā)至指定服務(wù)器處理 |
| ngx_http_fastcgi_module | 將客戶端對php的請求以fastcgi協(xié)議轉(zhuǎn)發(fā)至指定服務(wù)器助理 |
| ngx_http_uwsgi_module | 將客戶端對Python的請求以uwsgi協(xié)議轉(zhuǎn)發(fā)至指定服務(wù)器處理 |
| ngx_http_headers_module | 可以實現(xiàn)對頭部報文添加指定的key與值 |
| ngx_http_upstream_module | 負(fù)載均衡模塊,提供服務(wù)器分組轉(zhuǎn)發(fā)、權(quán)重分配、狀態(tài)監(jiān)測、調(diào)度算法等高級功能 |
| ngx_stream_upstream_module | 后端服務(wù)器分組轉(zhuǎn)發(fā)、權(quán)重分配、狀態(tài)監(jiān)測、調(diào)度算法等高級功能 |
| ngx_http_fastcgi_module | 實現(xiàn)通過fastcgi協(xié)議將指定的客戶端請求轉(zhuǎn)發(fā)至php-fpm處理 |
| ngx_http_flv_module | 為flv偽流媒體服務(wù)端提供支持 |
1、Nginx 的模塊從結(jié)構(gòu)上分為核心模塊、基礎(chǔ)模塊和第三方模塊
核心模塊:HTTP 模塊、EVENT 模塊和 MAIL 模塊;
基礎(chǔ)模塊:HTTP Access 模塊、HTTP FastCGI 模塊、HTTP Proxy 模塊和 HTTP Rewrite 模塊;
第三方模塊:HTTP Upstream Request Hash 模塊、Notice 模塊和 HTTP Access Key 模 塊。
2、Nginx 的模塊從功能上分為如下三類:
Handlers(處理器模塊):此類模塊直接處理請求,并進(jìn)行輸出內(nèi)容和修改 headers 信息等操作。Handlers 處理器模塊一般只能有一個;
Filters(過濾器模塊):此類模塊主要對其他處理器模塊輸出的內(nèi)容進(jìn)行修改操作,最后由 Nginx 輸出;Proxies(代理類模塊):此類模塊是 Nginx 的 HTTP
Upstream 之類的模塊,這些模塊主要與后端一些服務(wù)比如 FastCGI 等進(jìn)行交互,實現(xiàn)服務(wù)代理和負(fù)載均衡等功能。
Nginx rewrite概述
https://blog.csdn.net/July_jojo/article/details/109739494
3、Nginx 的進(jìn)程模型
在工作方式上,Nginx 分為單工作進(jìn)程和多工作進(jìn)程兩種模式。
1、在單工作進(jìn)程模式下,除主進(jìn)程外,還有一個工作進(jìn)程,工作進(jìn)程是單線程的;
2、在多工作進(jìn)程模式下,每個工作進(jìn)程包含多個線程。Nginx 默認(rèn)為單工作進(jìn)程模式。
Nginx 在啟動后,會有一個 master 進(jìn)程和多個 worker 進(jìn)程。
master 進(jìn)程主要用來管理 worker 進(jìn)程,主要包含:接收來自外界的信號,向各 worker 進(jìn)程發(fā)送信號,監(jiān)控 worker 進(jìn)程的運(yùn)行狀態(tài),當(dāng) worker 進(jìn)程退出后(異常情況下),會自動 重新啟動新的 worker 進(jìn)程。 master 進(jìn)程充當(dāng)整個進(jìn)程組與用戶的交互接口,同時對進(jìn)程進(jìn)行監(jiān)護(hù)。它不需要處理網(wǎng)絡(luò)事件,不負(fù)責(zé)業(yè)務(wù)的執(zhí)行,只會通過管理worker 進(jìn)程來實現(xiàn)重啟服務(wù)、平滑升級、更換日志文件、配置文件實時生效等功能。
二、Nginx優(yōu)點(diǎn)
1、優(yōu)點(diǎn)
跨平臺、配置簡單。
非阻塞、高并發(fā)連接
處理 2-3 萬并發(fā)連接數(shù),官方監(jiān)測能支持 5 萬并發(fā)。
內(nèi)存消耗小
開啟 10 個 Nginx 才占 150M 內(nèi)存
成本低廉,且開源。
穩(wěn)定性高,宕機(jī)的概率非常小。
主要功能:
1)正向、反向代理
2)負(fù)載均衡、分流
2)充當(dāng)一個虛擬主機(jī)(綁定host)
1、工作在網(wǎng)絡(luò)的7層之上,可以針對http應(yīng)用做一些分流的策略,比如針對域名、目錄結(jié)構(gòu),它的正則規(guī)則比HAProxy更為強(qiáng)大和靈活,這也是它目前廣泛流行的主要原因之一,Nginx單憑這點(diǎn)可利用的場合就遠(yuǎn)多于LVS了。2、Nginx對網(wǎng)絡(luò)穩(wěn)定性的依賴非常小,理論上能ping通就就能進(jìn)行負(fù)載功能,這個也是它的優(yōu)勢之一3、Nginx安裝和配置比較簡單,測試起來比較方便,它基本能把錯誤用日志打印出來。4、可以承擔(dān)高負(fù)載壓力且穩(wěn)定,在硬件不差的情況下一般能支撐幾萬次的并發(fā)量,負(fù)載度較小 (比LVS)5、Nginx可以通過端口檢測到服務(wù)器內(nèi)部的故障,比如根據(jù)服務(wù)器處理網(wǎng)頁返回的狀態(tài)碼、超時等等,并且會把返回錯誤的請求重新提交到另一個節(jié)點(diǎn),不過其中缺點(diǎn)就是不支持url來檢測。比如用戶正在上傳一個文件,而處理該上傳的節(jié)點(diǎn)剛好在上傳過程中出現(xiàn)故障,Nginx會把上傳切到另一臺服務(wù)器重新處理6、Nginx不僅僅是一款優(yōu)秀的負(fù)載均衡器/反向代理軟件,它同時也是功能強(qiáng)大的Web應(yīng)用服務(wù)器。LNMP也是近幾年非常流行的web架構(gòu),在高流量的環(huán)境中穩(wěn)定性也很好。7、Nginx現(xiàn)在作為Web反向加速緩存越來越成熟了,速度比傳統(tǒng)的Squid服務(wù)器更快,可以用作為反向代理加速器。8、Nginx可作為中層反向代理使用,這一層面Nginx基本上無對手,唯一可以對比Nginx的就只有 lighttpd了,不過 lighttpd目前還沒有做到Nginx完全的功能,配置也不那么清晰易讀,社區(qū)資料也遠(yuǎn)遠(yuǎn)沒Nginx活躍。9、Nginx也可作為靜態(tài)網(wǎng)頁和圖片服務(wù)器,這方面的性能也無對手。還有Nginx社區(qū)非常活躍,第三方模塊也很多。缺點(diǎn)
Nginx的缺點(diǎn)是: Nginx僅能支持http、https和Email協(xié)議,這樣就在適用范圍上面小些,這個是它的缺點(diǎn)。 對后端服務(wù)器的健康檢查,只支持通過端口來檢測,不支持通過url來檢測。不支持Session的直接保持,但能通過ip_hash來解決。2、正向代理和反向代理的區(qū)別
1)正向代理
是一個位于客戶端和目標(biāo)服務(wù)器之間的服務(wù)器,為了從目標(biāo)服務(wù)器取得內(nèi)容,客戶端向代理發(fā)送一個請求并指定目標(biāo)服務(wù)器,然后代理向目標(biāo)服務(wù)器轉(zhuǎn)交請求并將獲得的內(nèi)容返回給客戶端。代理服務(wù)器和客戶端處于同一個局域網(wǎng)內(nèi)。
比如說fanqiang。我知道我要訪問谷歌,于是我就告訴它讓它幫我轉(zhuǎn)發(fā)。
2)反向代理
up
實際運(yùn)行方式是代理服務(wù)器接受網(wǎng)絡(luò)上的連接請求。它將請求轉(zhuǎn)發(fā)給內(nèi)部網(wǎng)絡(luò)上的服務(wù)器,并將從服務(wù)器上得到的結(jié)果返回給網(wǎng)絡(luò)上請求連接的客戶端 。代理服務(wù)器和目標(biāo)服務(wù)器處于同一個局域網(wǎng)內(nèi)。
比如說我要訪問taobao,對我來說不知道圖片、json、css 是不是同一個服務(wù)器返回回來的,但是我不關(guān)心,是反向代理 處理的,我不知道目標(biāo)服務(wù)器。
反向代理配置:vim /etc/nginx/nginx.conf
stream {log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';access_log /var/log/nginx/k8s-access.log main;upstream k8s-apiserver {server 192.168.195.149:6443;server 192.168.195.131:6443;}server {listen 6443;proxy_pass k8s-apiserver;}}3、Nginx如何處理HTTP請求的?
它結(jié)合多進(jìn)程機(jī)制(單線程)和異步非阻塞方式。
1)多進(jìn)程機(jī)制(單線程)
服務(wù)器每當(dāng)收到一個客戶端時,就有 服務(wù)器主進(jìn)程 ( master process )生成一個 子進(jìn)程( worker process )出來和客戶端建立連接進(jìn)行交互,直到連接斷開,該子進(jìn)程就結(jié)束了。
2)異步非阻塞機(jī)制
每個工作進(jìn)程 使用 異步非阻塞方式 ,可以處理 多個客戶端請求 。 運(yùn)用了epoll模型,提供了一個隊列,排隊解決。
當(dāng)某個 工作進(jìn)程 接收到客戶端的請求以后,調(diào)用 IO 進(jìn)行處理,如果不能立即得到結(jié)果,就去 處理其他請求 (即為 非阻塞 );而 客戶端 在此期間也 無需等待響應(yīng) ,可以去處理其他事情(即為 異步 )。
當(dāng) IO 返回時,就會通知此 工作進(jìn)程 ;該進(jìn)程得到通知,暫時 掛起 當(dāng)前處理的事務(wù)去 響應(yīng)客戶端請求
4、Nginx的master和worker
這跟Nginx的多進(jìn)程、單線程有關(guān)。(一個進(jìn)程只有一個主線程)。
為什么要用單線程?
采用單線程來異步非阻塞處理請求(管理員可以配置Nginx主進(jìn)程的工作進(jìn)程的數(shù)量),不會為每個請求分配cpu和內(nèi)存資源,節(jié)省了大量資源,同時也減少了大量的CPU的上下文切換,所以才使得Nginx支持更高的并發(fā)。
簡單過程:
主程序 Master process 啟動后,通過一個 for 循環(huán)來 接收 和 處理外部信號 ;
主進(jìn)程通過 fork() 函數(shù)產(chǎn)生 worker 子進(jìn)程 ,每個子進(jìn)程執(zhí)行一個 for循環(huán)來實現(xiàn)Nginx服務(wù)器對事件的接收和處理 。
詳細(xì)過程:
1、Nginx 在啟動后,會有一個 master 進(jìn)程和多個相互獨(dú)立的 worker 進(jìn)程。 2、master 接收來自外界的信號,先建立好需要 listen 的 socket(listenfd) 之后,然后再 fork 出多個 worker 進(jìn)程,然后向各worker進(jìn)程發(fā)送信號,每個進(jìn)程都有可能來處理這個連接。 3、所有 worker 進(jìn)程的 listenfd 會在新連接到來時變得可讀 ,為保證只有一個進(jìn)程處理該連接,所有 worker 進(jìn)程在注冊 listenfd 讀事件前搶占 accept_mutex ,搶到互斥鎖的那個進(jìn)程注冊 listenfd 讀事件 ,在讀事件里調(diào)用 accept 接受該連接。 4、當(dāng)一個 worker 進(jìn)程在 accept 這個連接之后,就開始讀取請求、解析請求、處理請求,產(chǎn)生數(shù)據(jù)后,再返回給客戶端 ,最后才斷開連接。
5、Nginx 常用命令
啟動 nginx 。
停止 nginx -s stop 或 nginx -s quit 。
重啟 nginx -s reload 或 service nginx reload 。
重載指定配置文件 .nginx -c /usr/local/nginx/conf/nginx.conf 。
查看 nginx 版本 nginx -v 。
6、Nginx狀態(tài)碼
https://www.php.cn/course/1020.html
1)3開頭
301:請求資源已被永久移動位置 302:請求的資源現(xiàn)在臨時從不同的URL響應(yīng)請求 303:查看其他,對應(yīng)當(dāng)前請求的響應(yīng)可以在另一個URI上被找到 305:使用代理。被請求的資源必須通過指定的代理才能被訪問 307:臨時跳轉(zhuǎn)。被請求的資源在臨時從不同的URL響應(yīng)請求2)4開頭
400:錯誤請求。 402:需要付款。該狀態(tài)碼是為了將來可能需求而預(yù)留的,用于一些數(shù)字貨幣或者微支付 403:禁止訪問。服務(wù)器已理解請求,但是拒絕執(zhí)行它 404:找不到對象,請求失敗,資源不存在 406:不可接受的,請求的資源的內(nèi)容特性無法滿足請求頭中的條件,因而無法生成響應(yīng)實體 408:請求超時; 409:沖突。由于和被請求的資源的當(dāng)前狀態(tài)之間存在沖突,請求無法完成; 410:遺失的。被請求的資源在服務(wù)器上已經(jīng)不再可用,而且沒有任何已知的轉(zhuǎn)發(fā)地址; 413:響應(yīng)實體太大。服務(wù)器拒絕處理當(dāng)前請求,請求超過服務(wù)器所能處理和允許的最大值。 417:期望失敗。在請求頭 Expect 中指定的預(yù)期內(nèi)容無法被服務(wù)器滿足; 418:我是一個茶壺。超文本咖啡罐控制協(xié)議,但是并沒有被實際的HTTP服務(wù)器實現(xiàn) 420:方法失效。 422:不可處理的實體。請求格式正確,但是由于含有語義錯誤,無法響應(yīng);3)5開頭
500:Internal Server Error 內(nèi)部服務(wù)錯誤,比如腳本錯誤,編程語言語法錯誤。 502:Bad Gateway錯誤,網(wǎng)關(guān)錯誤。比如服務(wù)器當(dāng)前連接太多,響應(yīng)太慢,頁面素材太多、帶寬慢。 503:Service Temporarily Unavailable,服務(wù)不可用,web服務(wù)器不能處理HTTP請求,可能是臨時超載或者是服務(wù)器進(jìn)行停機(jī)維護(hù)。 504:Gateway timeout 網(wǎng)關(guān)超時,程序執(zhí)行時間過長導(dǎo)致響應(yīng)超時,例如程序需要執(zhí)行20秒,而nginx最大響應(yīng)等待時間為10秒,這樣就會出現(xiàn)超時。7、Nginx 壓縮
為什么要開啟壓縮?
開啟nginx gzip壓縮后,圖片、css、js等靜態(tài)資源的大小會減小,可節(jié)省帶寬,提高傳輸效率,但是會消耗CPU資源。
開啟:
? # 開啟gzip
gzip off;? # 啟用gzip壓縮的最小文件,小于設(shè)置值的文件將不會壓縮
gzip_min_length 1k;? # gzip 壓縮級別,1-9,數(shù)字越大壓縮的越好,也越占用CPU時間
gzip_comp_level 1;? # 進(jìn)行壓縮的文件類型。javascript有多種形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;8、Nginx 和 Apache、Tomcat 之間的不同點(diǎn)
1、Nginx/Apache 是Web Server,而Apache Tomact是一個servlet container
2、tomcat可以對jsp進(jìn)行解析,nginx和apache只是web服務(wù)器,可以簡單理解為只能提供html靜態(tài)文件服務(wù)。
Nginx和Apache區(qū)別:
1)Nginx輕量級,同樣起web 服務(wù),比apache占用更少的內(nèi)存及資源 。
2)Nginx 抗并發(fā),nginx 處理請求是異步非阻塞的,而apache 則是阻塞型的,在高并發(fā)下nginx 能保持低資源低消耗高性能 。
3)Nginx提供負(fù)載均衡,可以做做反向代理,前端服務(wù)器
4)Nginx多進(jìn)程單線程,異步非阻塞;Apache多進(jìn)程同步,阻塞。
9、Nginx動靜態(tài)資源分離
動態(tài)資源、靜態(tài)資源分離,是讓動態(tài)網(wǎng)站里的動態(tài)網(wǎng)頁根據(jù)一定規(guī)則把不變的資源和經(jīng)常變的資源區(qū)分開來
比如說 js、css、hrml從A服務(wù)器返回。圖片 從B服務(wù)器返回,其他請求從Tomcat服務(wù)器C返回。
后臺應(yīng)用分開部署,提高用戶訪問靜態(tài)代碼的速度。而且現(xiàn)在還有CDN服務(wù),不需要限制于服務(wù)器的帶寬。
10、ngx_http_upstream_module
ngx_http_upstream_module模塊用于將多個服務(wù)器定義成服務(wù)器組,可通過fastcgi傳遞、proxy傳遞、uwsgi傳遞、memcached傳遞和scgi傳遞指令來引用的服務(wù)器組。
比如訪問www.a.com 緩存+調(diào)度:
http{ proxy_cache_path /var/cache/nginx/proxy_cache levels=1:2:2 keys_zone=proxycache:20m inactive=120s max_size=1g; #緩存 upstream mysqlsrvs{ ip_hash; #源地址hash調(diào)度方法 寫了backup就不可用 server 172.18.99.1:80 weight=2; #weight權(quán)重 server 172.18.99.2:80; #標(biāo)記down,配合ip_hash使用,實現(xiàn)灰度發(fā)布 server 172.18.99.3:80 backup; #backup將服務(wù)器標(biāo)記為“備用”,即所有服務(wù)器均不可用時才啟用 }}server{ server_name www.a.com; proxy_cache proxycache; proxy_cache_key $request_uri; proxy_cache_valid 200 302 301 1h; proxy_cache_valid any 1m; location / { proxy_pass http://mysqlsrvs; }}11、限流了解嗎,怎么限流的?
Nginx 提供兩種限流方式,一是控制速率,二是控制并發(fā)連接數(shù)。
1、控制速率
ngx_http_limit_req_module 模塊提供了漏桶算法(leaky bucket),可以限制單個IP的請求處理頻率。
如:
1.1 正常限流:
http {limit_req_zone 192.168.1.1 zone=myLimit:10m rate=5r/s; }server {location / {limit_req zone=myLimit;rewrite / http://www.hac.cn permanent; }}參數(shù)解釋:
key: 定義需要限流的對象。
zone: 定義共享內(nèi)存區(qū)來存儲訪問信息。
rate: 用于設(shè)置最大訪問速率。
表示基于客戶端192.168.1.1進(jìn)行限流,定義了一個大小為10M,名稱為myLimit的內(nèi)存區(qū),用于存儲IP地址訪問信息。rate設(shè)置IP訪問頻率,rate=5r/s表示每秒只能處理每個IP地址的5個請求。Nginx限流是按照毫秒級為單位的,也就是說1秒處理5個請求會變成每200ms只處理一個請求。如果200ms內(nèi)已經(jīng)處理完1個請求,但是還是有有新的請求到達(dá),這時候Nginx就會拒絕處理該請求。
1.2 突發(fā)流量限制訪問頻率
上面rate設(shè)置了 5r/s,如果有時候流量突然變大,超出的請求就被拒絕返回503了,突發(fā)的流量影響業(yè)務(wù)就不好了。
這時候可以加上burst 參數(shù),一般再結(jié)合 nodelay 一起使用。
server {location / {limit_req zone=myLimit burst=20 nodelay;rewrite / http://www.hac.cn permanent; }}burst=20 nodelay 表示這20個請求立馬處理,不能延遲,相當(dāng)于特事特辦。不過,即使這20個突發(fā)請求立馬處理結(jié)束,后續(xù)來了請求也不會立馬處理。burst=20 相當(dāng)于緩存隊列中占了20個坑,即使請求被處理了,這20個位置這只能按 100ms一個來釋放。
2、控制并發(fā)連接數(shù)
ngx_http_limit_conn_module 提供了限制連接數(shù)功能。
limit_conn_zone $binary_remote_addr zone=perip:10m;limit_conn_zone $server_name zone=perserver:10m;server { ... limit_conn perip 10; limit_conn perserver 100;}limit_conn perip 10 作用的key 是 $binary_remote_addr,表示限制單個IP同時最多能持有10個連接。
limit_conn perserver 100 作用的key是 $server_name,表示虛擬主機(jī)(server) 同時能處理并發(fā)連接的總數(shù)。
注:limit_conn perserver 100 作用的key是 $server_name,表示虛擬主機(jī)(server) 同時能處理并發(fā)連接的總數(shù)。
拓展:
如果不想做限流,還可以設(shè)置白名單:
利用 Nginx ngx_http_geo_module 和 ngx_http_map_module 兩個工具模塊提供的功能。
##定義白名單ip列表變量
geo $limit { default 1; 10.0.0.0/8 0; 192.168.0.0/10 0; 81.56.0.35 0;}map $limit $limit_key { 0 ""; 1 $binary_remote_addr;}# 正常限流設(shè)置
limit_req_zone $limit_key zone=myRateLimit:10m rate=10r/s;geo 對于白名單 將返回0,不限流;其他IP將返回1,進(jìn)行限流。
具體參考:http://nginx.org/en/docs/http/ngx_http_geo_module.html
除此之外:
ngx_http_core_module 還提供了限制數(shù)據(jù)傳輸速度的能力(即常說的下載速度)
location /flv/ { flv; limit_rate_after 500m; limit_rate 50k;}針對每個請求,表示客戶端下載前500m的大小時不限速,下載超過了500m后就限速50k/s。
12、nginx重定向,重寫URL
URL重寫有利于網(wǎng)站首選域的確定,對于同一資源頁面多條路徑的301重定向有助于URL權(quán)重的集中
處理高并發(fā):
https://blog.csdn.net/asqi1/article/details/41478111
單個Nginx并發(fā)盡量不要超過2w,如果你的并發(fā)都達(dá)到10w了,是時候做DNS分流了,還不行的話,就應(yīng)該像Google那樣直接從網(wǎng)卡驅(qū)動層分流了
13、nginx是如何實現(xiàn)高并發(fā)的?
答:nginx之所以可以實現(xiàn)高并發(fā),與它采用的epoll模型有很大的關(guān)系。epoll模型采用異步非阻塞的事件處理機(jī)制。這種機(jī)制可讓nginx進(jìn)程同時監(jiān)控多個事件。
簡單來說,就是異步非阻塞,使用了epoll模型和大量的底層代碼優(yōu)化。如果深入一點(diǎn)的話,就是nginx的特殊進(jìn)程模型和事件模型的設(shè)計,才使其可以實現(xiàn)高并發(fā)。
進(jìn)程模型
它是采用一個master進(jìn)程和多個worker進(jìn)程的工作模式。1、master進(jìn)程主要負(fù)責(zé)收集、分發(fā)請求。當(dāng)一個請求過來時,master拉起一個worker進(jìn)程負(fù)責(zé)處理這個請求。;2、master進(jìn)程也要負(fù)責(zé)監(jiān)控worker的狀態(tài),保證高可靠性;3、worker進(jìn)程議案設(shè)置為和CPU核心數(shù)一致或者其二倍。nginx的worker進(jìn)程和Apache的不一樣。apache的進(jìn)程在同一時間只能處理一個請求,所以它會開啟很多個進(jìn)程,幾百甚至幾千個。而nginx的worker進(jìn)程在同一時間可以處理的請求數(shù)只受內(nèi)存限制,因此可以處理更多請求。事件模型
nginx是異步非阻塞的。
一個master進(jìn)程,多個worker進(jìn)程,每個worker進(jìn)程可以處理多個請求。每進(jìn)來一個request,都會有worker進(jìn)程去處理。但不是全程的處理,那么處理到的程度就是可能發(fā)生阻塞的地方,比如向后端服務(wù)器轉(zhuǎn)發(fā)request,并等待請求返回。那么,在等待期間,這個處理的worker不會這么傻等著,他會在發(fā)送完請求后,注冊一個事件:“如果upstream返回了,告訴我一聲,我再接著干”。于是它就去休息了,此時,如果再有request進(jìn)來,它就可以很快再按這種方式處理。而一旦后端服務(wù)器返回了,就會觸發(fā)這個事件,worker才會來接手,這個request才會接著往下走。
由于nginx的的這個工作性質(zhì)決定了每個請求大部分的生命都是在網(wǎng)絡(luò)傳輸中,所以實際上花費(fèi)在nginx 服務(wù)器上的時間并不多,這就是它幾進(jìn)程就能解決高并發(fā)的秘密所在。
14、使用nginx代理后,獲取用戶真實ip
使用nginx轉(zhuǎn)發(fā)請求時,應(yīng)用中獲取到的用戶ip 都是127.0.0.1,獲取真實ip必須重寫一些頭部才行。通常在WSGI環(huán)境中經(jīng)常使用的變量:REMOTE_ADDR ,在nginx轉(zhuǎn)發(fā)時設(shè)置頭部攜帶這個變量
nginx設(shè)置
server { listen 80; server_name _; location / { .................. proxy_pass http://127.0.0.1:8000/; # $host 變量,Host 為變量名 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }}可以從proxy_add_x_forwarded_for中獲取到用戶的真實IP,
也可以通過后臺的程序,從請求的header里獲取X-Forwarded-For,然后取起一個值即可,使用正則匹配獲取第一個即可,如下:
location / { proxy_set_header Host $host; set $Real $proxy_add_x_forwarded_for; if (Real ~ ( d+) i. (1d+) i. (sd+) i. (d+),(.*) ){ set$Real $1.$2.$3.$4; } proxy_set_header X-real-ip $Real; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}proxy_set_header 和add_header 的區(qū)別
區(qū)別: proxy_set_header是Nginx設(shè)置請求頭信息給上游服務(wù)器, add_header是Nginx設(shè)置響應(yīng)頭信息給瀏覽器。
proxy_set_header
假如Nginx請求上游服務(wù)器時,添加額外的請求頭,就需要使用proxy_set_header。
三、Nginx的優(yōu)化
配置nginx的proxy緩存;
對靜態(tài)頁面開啟壓縮功能,如br壓縮或者gzip壓縮;
調(diào)整nginx運(yùn)行工作進(jìn)程個數(shù),最多開啟8個,8個以上話性能就不會再提升了,而且穩(wěn)定性變得更低,所以8個足夠用了;
調(diào)整nginx運(yùn)行CPU的親和力;
修改nginx最多可打開的文件數(shù),若超過系統(tǒng)限制的最多打開文件數(shù)(ulimit -n命令查看系統(tǒng)的最多打開文件數(shù)),還需要修改系統(tǒng)默認(rèn)的文件數(shù);
修改單個worker的最大連接數(shù);
開啟高效傳輸;
設(shè)置連接超時時間,以便保護(hù)服務(wù)器資源,因為建立連接也是需要消耗資源的;
優(yōu)化fastCGI的一個超時時間,也可以根據(jù)實際情況對其配置緩存動態(tài)頁面;
expires緩存調(diào)優(yōu),主要針對圖片、css、js等元素更改較少的情況下使用。
配置防盜鏈;
優(yōu)化內(nèi)核參數(shù),如進(jìn)程可以同時打開的最大句柄數(shù);開啟tcp重用機(jī)制,以便允許TIME_WAIT sockets重新用于新的TCP連接…
1、隱藏版本號
隱藏Nginx版本號有兩種方式:
第一種是修改Nginx源碼文件,指定不顯示版本號
第二種是修改Nginx的主配置文件
[root@localhost ~]# curl -I http://20.0.0.6 ### 查看網(wǎng)站版本號HTTP/1.1 200 OK Server: nginx/1.15.9 ### 版本號Date: Sun, 06 Sep 2020 05:52:47 GMT1)修改配置文件方式
將Nginx的配置文件中的server_tokens選項值設(shè)置為off,如果有該配置項,加上即可
[root@localhost ~]# vi /usr/local/nginx/conf/nginx.confhttp { include mime.types; default_type application/octet-stream; server_tokens off; ###此處新增代碼,含義是將版本號關(guān)閉 [root@localhost ~]# nginx -t ### 檢查配置是否正常nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful[root@localhost ~]# systemctl restart nginx.service ### 重啟服務(wù)測試:然后用Wireshark抓包軟件抓包測試一下,版本號還能看到嗎
2)設(shè)置版本信息
Nginx源碼文件/opt/nginx-1.15.9/src/core/nginx.h包含了版本信息,可以隨意設(shè)置,然后重新編譯安裝,隱藏版本信息。
[root@localhost ~]# vi /opt/nginx-1.15.9/src/core/nginx.h #define NGINX_VERSION "1.1.1" ### 修改版本號#define NGINX_VER "IIS" NGINX_VERSION ### 修改服務(wù)器類型[root@localhost ~]# cd /opt/nginx-1.15.9/[root@localhost nginx-1.15.9]# ./configure \--prefix=/usr/local/nginx \--user=nginx \--group=nginx \--with-http_stub_status_module[root@localhost nginx-1.15.9]# make -j3 && make install[root@localhost nginx-1.15.9]# cd /usr/local/nginx/conf/[root@localhost conf]# vi nginx.confhttp { include mime.types; default_type application/octet-stream; server_tokens on; ### 打開版本號[root@localhost conf]# systemctl restart nginx.service ###重啟[root@localhost conf]# curl -I http://20.0.0.6HTTP/1.1 200 OKServer: IIS 1.1.1 ### 版本號和服務(wù)器類型已經(jīng)更改Date: Sun, 06 Sep 2020 06:34:21 GMTContent-Type: text/htmlContent-Length: 612Last-Modified: Sun, 06 Sep 2020 06:14:14 GMTConnection: keep-aliveETag: "5f547e36-264"Accept-Ranges: bytes2、修改用戶與組
1)指定用戶與組參數(shù)
configure編譯過程中指定用戶和組參數(shù)為nginx
[root@localhost ~]# cd /opt/nginx-1.15.9/[root@localhost nginx-1.15.9]# ./configure \--prefix=/usr/local/nginx \--user=nginx \--group=nginx \--with-http_stub_status_module2)配置用戶與組
修改Nginx配置文件的Nginx指定用戶與組
[root@localhost opt]# cd /usr/local/nginx/conf/[root@localhost conf]# vi nginx.confuser nginx nginx; ### 修改用戶為nginx,組為nginx[root@localhost conf]# systemctl restart nginx[root@localhost conf]# ps aux |grep nginxroot 23044 0.0 0.0 20560 628 ? Ss 02:40 0:00 nginx: master process /usr/local/nginx/sbin/nginxnginx 23045 0.0 0.0 23100 1396 ? S 02:40 0:00 nginx: worker processroot 23059 0.0 0.0 112708 976 pts/0 S+ 02:41 0:00 grep --color=auto nginx重啟Nginx查看進(jìn)程運(yùn)行情況,主進(jìn)程由root賬戶創(chuàng)建,子進(jìn)程由Nginx創(chuàng)建。
3、配置網(wǎng)頁緩存時間
1、以圖片作為緩存對象,上傳51xit.jpg圖片到/usr/local/nginx/html的工作目錄,訪問http://20.0.0.6/51xit.jpg,用wireshark工具進(jìn)行抓包,查看響應(yīng)報文,沒有圖片的緩存信息查看報文沒有緩存信息
2、修改Nginx的配置文件,在新location段加入expires參數(shù),指定緩存的時間1d一天
[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf location ~ \.(gif|jpg|jepg|png|bmp|ico)$ { root html; expires 1d; ### 指定緩存時間1天 }3、重啟Nginx服務(wù),訪問wireshark抓包
[root@localhost ~]# systemctl restart nginx ### 重啟nginx服務(wù)
測試:在/usr/local/nginx/html里面添加一張51xit.jpg圖片,然后wireshark抓包查看一下緩存時間對不對
4、日志分割
日志切割 隨著Nginx運(yùn)行時間的增加, 產(chǎn)生的日志也會逐漸增加,為了方便掌握Nginx的運(yùn)行 狀態(tài), 需要時刻關(guān)注Nginx日志文件。太大的日志文件對監(jiān)控是一個大災(zāi)難,不便于分析排查,需要定期的進(jìn)行日志文件的切割。
##編寫腳本/opt/feng e.sh##
把Nginx的日志文件/usr/local/nginx/logs/access.log移動到, 目錄/var/log/ng in x下面, 以當(dāng)前時間做為日志文件的名稱, 然后用kill-USR1創(chuàng)建新的日志文件/usr/local/nginx/logs/access.log, 最后刪除30天之前的日志文件。
[root@localhost ~]# vi /opt/fenge.sh#!/bin/bash# Filename: fenge.shd=$(date -d "-1 day" "+%Y%m%d")logs_path="/var/log/nginx"pid_path="/usr/local/nginx/logs/nginx.pid"[ -d $logs_path ] || mkdir -p $logs_pathmv /usr/local/nginx/logs/access.log ${logs_path}/test.com-access.log-$dkill -USR1 $(cat $pid_path)find $logs_path -mtime +30 |xargs rm -rf---------------上面解釋----------------------------------------------------------------
#!/bin/bash# Filename: fenge.shd=$(date -d "-1 day" "+%Y%m%d")logs_path="/var/log/nginx" ###分割到nginx目錄去pid_path="/usr/local/nginx/logs/nginx.pid" ###重新生成新的日志文件[ -d $logs_path ] || mkdir -p $logs_path ###如果沒有nginx目錄就會創(chuàng)建mv /usr/local/nginx/logs/access.log ${logs_path}/test.com-access.log-$d ###把原有路徑的日志文件移出來,改成那天的日期名字kill -USR1 $(cat $pid_path) ###結(jié)束當(dāng)時的進(jìn)程,生成一個新pid,然后生成新的日志文件find $logs_path -mtime +30 |xargs rm -rf ###找到30天之前的刪除掉------------------------------------------------------------------------------------------
[root@localhost ~]# chmod +x /opt/fenge.sh ###給執(zhí)行權(quán)限[root@localhost opt]# ./fenge.sh ### 執(zhí)行分割腳本[root@localhost opt]# ls /var/log/nginx/test.com-access.lo test.com-access.log-20200905 ###按日期分割了日志文件[root@localhost opt]# cat /usr/local/nginx/logs/access.log ###原來的位置文件重新創(chuàng)建########設(shè)置crotab任務(wù),定期執(zhí)行腳本自動進(jìn)行日志分割#########[root@localhost opt]# crontab -e30 1 * * * /opt/fenge.sh5、設(shè)置連接超時
在企業(yè)網(wǎng)站中,為了避免同一個客戶長時間占用連接,造成資源浪費(fèi),可設(shè)置相應(yīng)的連 接超時參數(shù), 實現(xiàn)控制連接訪問時間。可以修改配置文件nginx.conf, 設(shè)置keepalive_timeout 超時時間。
[root@localhost opt]# vi /usr/local/nginx/conf/nginx.conf keepalive_timeout 65 180; ### 默認(rèn)65秒,設(shè)置超時180秒 client_header_timeout 80; client_body_timeout 80;[root@localhost opt]# systemctl restart nginx ###重啟nginx服務(wù)測試:瀏覽器輸入20.0.0.6,然后wireshark抓包查看一下連接超時時間
##########深入優(yōu)化##############
6、更改進(jìn)程數(shù)
在高并發(fā)環(huán)境中,需要啟動更多的Nginx進(jìn)程以保證快速響應(yīng),用以處理用戶的請求,避免造成阻塞。使用ps aux命令查看Nginx運(yùn)行進(jìn)程的個數(shù)。
[root@localhost ~]# ps aux |grep nginxroot 76128 0.0 0.0 20560 628 ? Ss 03:26 0:00 nginx: master process /usr/local/nginx/sbin/nginxnginx 76129 0.0 0.0 23100 1652 ? S 03:26 0:00 nginx: worker processroot 76201 0.0 0.0 112708 972 pts/0 S+ 03:33 0:00 grep --color=auto nginx其中master是Nginx的主進(jìn)程,開啟了1個,worker 是子進(jìn)程,進(jìn)程也是開啟了1個。
修改Nginx的配置文件的worker_processes參數(shù), 一般設(shè)為CPU的個數(shù)或者核數(shù), 在高并發(fā)的情況下可設(shè)置為CPU個數(shù)或者核數(shù)的2倍, 可以查看CPU的核數(shù)以確定參數(shù)
[root@localhost ~]# cat /proc/cpuinfo |grep -c "physical" ###查看CPU的核數(shù)以確定參數(shù)。8[root@localhost ~]# vi /usr/local/nginx/conf/nginx.confworker_processes 8; ###根據(jù)剛剛查的核數(shù),把數(shù)字改成8.修改完后,重啟服務(wù),使用ps aux查看運(yùn)行進(jìn)程數(shù)的變化情況。[root@localhost ~]# ps aux|grep nginx ### 可以看到現(xiàn)在是8個進(jìn)程root 76329 0.0 0.0 20560 700 ? Ss 03:40 0:00 nginx: master process /usr/local/nginx/sbin/nginxnginx 76330 0.0 0.0 23100 1404 ? S 03:40 0:00 nginx: worker processnginx 76331 0.0 0.0 23100 1404 ? S 03:40 0:00 nginx: worker processnginx 76332 0.0 0.0 23100 1404 ? S 03:40 0:00 nginx: worker processnginx 76333 0.0 0.0 23100 1404 ? S 03:40 0:00 nginx: worker processnginx 76334 0.0 0.0 23100 1404 ? S 03:40 0:00 nginx: worker processnginx 76335 0.0 0.0 23100 1404 ? S 03:40 0:00 nginx: worker processnginx 76336 0.0 0.0 23100 1404 ? S 03:40 0:00 nginx: worker processnginx 76337 0.0 0.0 23100 1404 ? S 03:40 0:00 n7、配置網(wǎng)頁壓縮
[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf gzip on; gzip_buffers 4 64k; gzip_http_version 1.1; gzip_comp_level 2; gzip_min_length 1k; gzip_vary on; gzip_types text/plain text/javascript application/x-javascript text/css text/xml application/xml application/xml+rss;###上面的配置解釋###
gzip on:開啟gzip壓縮輸出; gzip_min_length 1k:用于設(shè)置允許壓縮的頁面最小字節(jié)數(shù);gzip_buffers 416k:表示申請4個單位為16k的內(nèi)存作為壓縮結(jié)果流緩存,默認(rèn)值 是申請與原始數(shù)據(jù)大小相同的內(nèi)存空間來存儲gzip壓縮結(jié)果; Zip_http_version 1.0:用于設(shè)置識別http協(xié)議版本, 默認(rèn)是1.1,目前大部分瀏覽 器已經(jīng)支持gzip解壓,但處理最慢,也比較消耗服務(wù)器CPU資源; Gzip_comp_level 2:用來指定gzip壓縮比, 1壓縮比最小, 處理速度最快; 9壓縮 比最大,傳輸速度快,但處理速度最慢,使用默認(rèn)即可;Gzip_types text/plain:壓縮類型, 是對哪些網(wǎng)頁文檔啟用壓縮功能;Gzip_vary on:選項可以讓前端的緩存服務(wù)器緩存經(jīng)過gzip壓縮的頁面[root@localhost ~]# vi /usr/local/nginx/html/index.html
xxxxxx
###在這里面隨便加?xùn)|西,讓index.html大于1k就行測試:瀏覽器輸入20.0.0.6/index.html,然后wireshark抓包查看一下壓縮情況。
8、配置防盜鏈
###防盜鏈需要準(zhǔn)備兩臺主機(jī)模擬盜鏈###
20.0.0.6 www.51xit.top 源主機(jī)
20.0.0.5 www.52xit.top 盜鏈主機(jī)
### 修改windows的 C:\Windows\System32\drivers\etc\host文件,設(shè)置域名和映射關(guān)系
20.0.0.6 www.51xit.top
20.0.0.5 www.52xit.top
###在盜鏈主機(jī)的工作目錄編寫盜鏈頁面index.html,即盜源主機(jī)的圖片###
[root@localhost ~]# cd /usr/local/httpd/htdocs/[root@localhost htdocs]# vi index.html <html><head><title>--盜圖測試--</title></head><body><h1>盜圖頁面</h1><img src=http://20.0.0.6/51xit.jpg /></body></html>測試:瀏覽器輸入20.0.0.5,查看能不能正常盜鏈
###在主機(jī)配置Nginx防盜鏈###
[root@localhost ~]# cd /usr/local/nginx/conf/[root@localhost conf]# vi nginx.conf location ~* \.(gif|jpg|jepg|png|bmp|ico)$ { valid_referers none blocked *.51xit.top 51xit.top; if ($invalid_referer) { rewrite ^/ https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=202451072,4165552475&fm=26&gp=0.jpg; }}[root@localhost conf]# systemctl restart nginx測試:瀏覽器輸入20.0.0.5,查看能不能防止盜鏈!!!
9、FPM參數(shù)優(yōu)化
####################安裝PHP環(huán)境#####
yum -y install \libjpeg \libjpeg-devel \libpng libpng-devel \freetype freetype-devel \libxml2 \libxml2-devel \zlib zlib-devel \curl curl-devel \openssl openssl-devel#######上傳php-7.1.10.tar.bz2包到opt目錄下#####
cd /opttar xjvf php-7.1.10.tar.bz2cd php-7.1.10./configure \--prefix=/usr/local/php \--with-apxs2=/usr/local/httpd/bin/apxs \--with-mysql-sock=/usr/local/mysql/mysql.sock \--with-mysqli \--with-zlib \--with-curl \--with-gd \--with-jpeg-dir \--with-png-dir \--with-freetype-dir \--with-openssl \--enable-mbstring \--enable-xml \--enable-session \--enable-ftp \--enable-pdo \--enable-tokenizer \--enable-zip make -j3 && make installcp php.ini-development /usr/local/php/lib/php.inivi /usr/local/php/lib/php.inimysqli.default_socket = /usr/local/mysql/mysql.sockdate.timezone = Asia/Shanghai[root@localhost php-7.1.10]# /usr/local/php/bin/php -m //驗證安裝的模塊[root@localhost php-7.1.10]# vi /etc/httpd.conf //在合適位置新增AddType application/x-httpd-php .php ###添加AddType application/x-httpd-php-source .phps ###添加<IfModule dir_module> DirectoryIndex index.php index.html ###找到這個添加</IfModule>[root@localhost php-7.1.10]# rm -f /usr/local/httpd/htdocs/index.html ###刪除[root@localhost php-7.1.10]# vi /usr/local/httpd/htdocs/index.php ###創(chuàng)建新的<?phpphpinfo();?>[root@localhost php-7.1.10]# systemctl restart httpd.service測試:20.0.0.6#####FPM參數(shù)優(yōu)化###
[root@localhost php-7.1.10]# cd /usr/local/php/etc/php-fpm.d[root@localhost etc]# vi www.confpm=dynamicpm.max_children=20pm.start_servers=5pm.min_spare_servers=2pm.max_spare_servers=8FPM啟動時有5個進(jìn)程,最小空閑2個進(jìn)程,最大空閑8個進(jìn)程,最多可以有20個進(jìn)程存在。
一、pm.max_children多大合適?
這個值原則上是越大越好, php-cgi的進(jìn)程多了就會處理的很快, 排隊的請求就會很少。
設(shè)置”max children”也需要根據(jù)服務(wù)器的性能進(jìn)行設(shè)定。
計算方式如下:
一般來說一臺服務(wù)器正常情況下每一個php-cgi所耗費(fèi)的內(nèi)存在20M~30M左右, 因此我的”max_children”我設(shè)置成40個,
20M*40=800M也就是說在峰值的時候所有PHP-CGI所耗內(nèi)存在800M以內(nèi), 低于我的有效內(nèi)存2Gb。
而如果我的”max_children”設(shè)置的較小, 比如5-10個, 那么php-cgi就會“很累“, 處理速度也很慢, 等待的時間也較長,占用的CPU也很高。
如果長時間沒有得到處理的請求就會出現(xiàn)504 Gateway Time-out這個錯誤, 而正在處理的很累的那幾個php-cgi如果遇到了問題就會出現(xiàn)502Bad gateway這個錯誤。
max_children較好的設(shè)置方式根據(jù)req/s(吞吐率, 單位時間里服務(wù)器處理的最大請求數(shù), 單位req/s) 來設(shè)置, 若程序是100D req/s的處理能力, 那么就設(shè)置100比較好, 這是動態(tài)來調(diào)整的。
10、內(nèi)核優(yōu)化
默認(rèn)的Linux內(nèi)核參數(shù)考慮的是最通用的場景,不符合用于支持高并發(fā)訪問的Web服務(wù)器的定義,所以需要修改Linux內(nèi)核參數(shù),使得Nginx可以擁有更高的性能。
內(nèi)核優(yōu)化基本上會根據(jù)業(yè)務(wù)特點(diǎn)來進(jìn)行調(diào)整,當(dāng)Nginx作為靜態(tài)Web內(nèi)容服務(wù)器、反向代理服務(wù)器或是提供圖片縮略功能(實時壓縮圖片)的服務(wù)器時,其內(nèi)核參數(shù)的調(diào)整都是不同的。這里只針對最通用的、使Nginx支持更多并發(fā)請求的TCP網(wǎng)絡(luò)參數(shù)做簡單說明。
首先,需要修改/etc/sysctl.conf來更改內(nèi)核參數(shù)
net.ipv4.tcp_max_tw_buckets = 6000 timewait 的數(shù)量,默認(rèn)是180000。net.ipv4.ip_local_port_range = 1024 65000 允許系統(tǒng)打開的端口范圍。net.ipv4.tcp_tw_recycle = 1 啟用timewait 快速回收。net.ipv4.tcp_tw_reuse = 1 開啟重用。允許將TIME-WAIT sockets 重新用于新的TCP 連接。net.ipv4.tcp_syncookies = 1 開啟SYN Cookies,當(dāng)出現(xiàn)SYN 等待隊列溢出時,啟用cookies 來處理。net.core.somaxconn = 262144web 應(yīng)用中l(wèi)isten 函數(shù)的backlog 默認(rèn)會給我們內(nèi)核參數(shù)的net.core.somaxconn 限制到128,而nginx 定義的NGX_LISTEN_BACKLOG 默認(rèn)為511,所以有必要調(diào)整這個值。net.core.netdev_max_backlog = 262144 每個網(wǎng)絡(luò)接口接收數(shù)據(jù)包的速率比內(nèi)核處理這些包的速率快時,允許送到隊列的數(shù)據(jù)包的最大數(shù)目。net.ipv4.tcp_max_orphans = 262144 系統(tǒng)中最多有多少個TCP 套接字不被關(guān)聯(lián)到任何一個用戶文件句柄上。如果超過這個數(shù)字,孤兒連接將即刻被復(fù)位并打印出警告信息。這個限制僅僅是為了防止簡單的DoS 攻擊,不能過分依靠它或者人為地減小這個值,更應(yīng)該增加這個值(如果增加了內(nèi)存之后)。net.ipv4.tcp_max_syn_backlog = 262144 記錄的那些尚未收到客戶端確認(rèn)信息的連接請求的最大值。對于有128M 內(nèi)存的系統(tǒng)而言,缺省值是1024,小內(nèi)存的系統(tǒng)則是128。net.ipv4.tcp_timestamps = 0 時間戳可以避免序列號的卷繞。一個1Gbps 的鏈路肯定會遇到以前用過的序列號。時間戳能夠讓內(nèi)核接受這種“異常”的數(shù)據(jù)包。這里需要將其關(guān)掉。net.ipv4.tcp_synack_retries = 1 為了打開對端的連接,內(nèi)核需要發(fā)送一個SYN 并附帶一個回應(yīng)前面一個SYN 的ACK。也就是所謂三次握手中的第二次握手。這個設(shè)置決定了內(nèi)核放棄連接之前發(fā)送SYN+ACK 包的數(shù)量。net.ipv4.tcp_syn_retries = 1 在內(nèi)核放棄建立連接之前發(fā)送SYN 包的數(shù)量。net.ipv4.tcp_fin_timeout = 1 如果套接字由本端要求關(guān)閉,這個參數(shù)決定了它保持在FIN-WAIT-2 狀態(tài)的時間。對端可以出錯并永遠(yuǎn)不關(guān)閉連接,甚至意外當(dāng)機(jī)。缺省值是60 秒。2.2 內(nèi)核的通常值是180 秒,3你可以按這個設(shè)置,但要記住的是,即使你的機(jī)器是一個輕載的WEB 服務(wù)器,也有因為大量的死套接字而內(nèi)存溢出的風(fēng)險,FIN- WAIT-2 的危險性比FIN-WAIT-1 要小,因為它最多只能吃掉1.5K 內(nèi)存,但是它們的生存期長些。net.ipv4.tcp_keepalive_time = 30 當(dāng)keepalive 起用的時候,TCP 發(fā)送keepalive 消息的頻度。缺省是2 小時。下面貼一個完整的內(nèi)核優(yōu)化設(shè)置:
vi /etc/sysctl.conf CentOS5.5中可以將所有內(nèi)容清空直接替換為如下內(nèi)容:
net.ipv4.ip_forward = 0net.ipv4.conf.default.rp_filter = 1net.ipv4.conf.default.accept_source_route = 0kernel.sysrq = 0kernel.core_uses_pid = 1net.ipv4.tcp_syncookies = 1kernel.msgmnb = 65536kernel.msgmax = 65536kernel.shmmax = 68719476736kernel.shmall = 4294967296net.ipv4.tcp_max_tw_buckets = 6000net.ipv4.tcp_sack = 1net.ipv4.tcp_window_scaling = 1net.ipv4.tcp_rmem = 4096 87380 4194304net.ipv4.tcp_wmem = 4096 16384 4194304net.core.wmem_default = 8388608net.core.rmem_default = 8388608net.core.rmem_max = 16777216net.core.wmem_max = 16777216net.core.netdev_max_backlog = 262144net.core.somaxconn = 262144net.ipv4.tcp_max_orphans = 3276800net.ipv4.tcp_max_syn_backlog = 262144net.ipv4.tcp_timestamps = 0net.ipv4.tcp_synack_retries = 1net.ipv4.tcp_syn_retries = 1net.ipv4.tcp_tw_recycle = 1net.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_mem = 94500000 915000000 927000000net.ipv4.tcp_fin_timeout = 1net.ipv4.tcp_keepalive_time = 30net.ipv4.ip_local_port_range = 1024 65000使配置立即生效可使用如下命令: /sbin/sysctl -p
四、Nginx負(fù)載均衡
1、四層和七層
1)四層負(fù)載四層就是基于IP+端口的負(fù)載均衡,通過虛擬IP+端口接收請求,然后再分配到真實的服務(wù)器;2)七層負(fù)載七層就是基于URL等應(yīng)用層信息的負(fù)載均衡,通過虛擬的URL或主機(jī)名接收請求,然后再分配到真實的服務(wù)器。3)二層、三層負(fù)載基于MAC地址的二層負(fù)載均衡:二層負(fù)載均衡會通過一個虛擬MAC地址接收請求,然后再分配到真實的MAC地址;基于IP地址的三層負(fù)載均衡:三層負(fù)載均衡會通過一個虛擬IP地址接收請求,然后再分配到真實的IP地址;2、熱備
如果你有2臺服務(wù)器,當(dāng)一臺服務(wù)器發(fā)生事故時,才啟用第二臺服務(wù)器給提供服務(wù)。服務(wù)器處理請求的順序:AAAAAA突然A掛啦,BBBBBBBBBBBBBB…
upstream mysvr { server 127.0.0.1:7878; server 192.168.10.121:3333 backup; #熱備 }3、負(fù)載均衡策略(算法)
Nginx 默認(rèn)提供的負(fù)載均衡策略:
1)輪詢(默認(rèn))round_robin
每個請求按時間順序逐一分配到不同的后端服務(wù)器,如果后端服務(wù)器down掉,能自動剔除。
雖然這種方式簡便、成本低廉。但缺點(diǎn)是:可靠性低和負(fù)載分配不均衡。
例如:
upstream backserver { server 192.168.0.14; server 192.168.0.15; }2)權(quán)重 weight
weight的值越大分配到的訪問概率越高,主要用于后端每臺服務(wù)器性能不均衡的情況下,達(dá)到合理的資源利用率。
配置方式:
upstream backserver { server 192.168.0.14 weight=8; server 192.168.0.15 weight=10; }3)IP 哈希 ip_hash
ip_hash: 來自同一個IP的請求會分發(fā)到相同的后端服務(wù)器
每個請求按訪問 ip 的 hash 結(jié)果分配,這樣每個訪客固定訪問一個后端服務(wù)器,可以解決 session 共享的問題。
當(dāng)然,實際場景下,一般不考慮使用 ip_hash 解決 session 共享。
例如:
upstream backserver { ip_hash; server 192.168.0.14:88; server 192.168.0.15:80; }4)最少連接 least_conn
把請求轉(zhuǎn)發(fā)給連接數(shù)較少的后端服務(wù)器。輪詢算法是把請求平均的轉(zhuǎn)發(fā)給各個后端,使它們的負(fù)載大致相同;但是,有些請求占用的時間很長,會導(dǎo)致其所在的后端負(fù)載較高。這種情況下,least_conn這種方式就可以達(dá)到更好的負(fù)載均衡效果。
#動態(tài)服務(wù)器組 upstream backserver { least_conn; #把請求轉(zhuǎn)發(fā)給連接數(shù)較少的后端服務(wù)器 server localhost:8080 weight=2; #tomcat 7.0 server localhost:8081; #tomcat 8.0 server localhost:8082 backup; #tomcat 8.5 server localhost:8083 max_fails=3 fail_timeout=20s; #tomcat 9.0 }5)fair(第三方)
按后端服務(wù)器的響應(yīng)時間來分配請求,響應(yīng)時間短的優(yōu)先分配。
6)url_hash(第三方)
按訪問url的hash結(jié)果來分配請求,使每個url定向到同一個后端服務(wù)器,后端服務(wù)器為緩存時比較有效。
補(bǔ)充:
sticky:通過nginx-sticky模塊,來實現(xiàn)cookie黏貼的方式將來自同一個客戶端的請求發(fā)送到同一個后端服務(wù)器上處理,這樣一定程度上可以解決多個后端服務(wù)器的session會話同步的問題;round-robin(RR):輪詢,每個請求按時間順序依次分配到不同的后端服務(wù)器,如果后端某臺服務(wù)器死機(jī),自動剔除故障系統(tǒng),使用戶訪問不受影響;weight:輪詢權(quán)重,weight的值越大分配到的訪問概率就越高,主要用于后端每臺服務(wù)器性能不均衡的情況下,或者僅僅為在主從的情況下設(shè)置不同的權(quán)重,達(dá)到合理有效的利用主機(jī)資源。least_conn:請求被發(fā)送到當(dāng)前活躍連接最少的realserver上,會考慮到weight的值;ip_hash:每個請求按照IP的哈希結(jié)果分配,使來自同一個IP的訪客固定訪問后端服務(wù)器,可以有效的解決動態(tài)網(wǎng)頁存在的session共享問題。fair:比weight、ip_hash更加智能的負(fù)載均衡算法,fair算法可以根據(jù)頁面的大小和加載時間長短智能地進(jìn)行負(fù)載均衡,也就是根據(jù)后端服務(wù)器的響應(yīng)時間來分配請求,相應(yīng)時間短的優(yōu)先分配。nginx本身不支持fair,如果需要使用這種調(diào)度算法,則必須安裝upstream_fair模塊。url_hash:按訪問的URL的哈希結(jié)果來分配請求,使每個URL定向到后端服務(wù)器,可以進(jìn)一步提高后端緩存服務(wù)器的效率。同樣,nginx本身不支持url_hash,如果需要這種調(diào)度算法,則必須安裝nginx的hash軟件包。4、負(fù)載均衡狀態(tài)
在nginx upstream模塊中,可以設(shè)定每臺后端服務(wù)器在負(fù)載均衡調(diào)度中的狀態(tài)。
常用的狀態(tài)有:down:表示當(dāng)前的server暫時不參與負(fù)載均衡;backup:預(yù)留的備份機(jī)器。當(dāng)其他所有的非backup機(jī)器出現(xiàn)故障或者繁忙的時候,才會請求backup機(jī)器,因此這臺機(jī)器的訪問壓力最低;max_fails:允許請求失敗的次數(shù),默認(rèn)為1,當(dāng)超過最大次數(shù)時,返回proxy_next_upstraem模塊定義的錯誤;fail_timeout:請求失敗超時時間,在經(jīng)歷了max_fails次失敗后,暫停服務(wù)的時間。max_fails和fail_timeout可以一起使用。六、FastCG、php-fpm
1、Nginx+FastCGI運(yùn)行原理
Nginx 不支持對外部程序的直接調(diào)用或者解析,所有的外部程序(包括 PHP)必須通過FastCGI 接口來調(diào)用。FastCGI 接口在 Linux 下是 socket(這個 socket 可以是文件 socket, 也可以是 ip socket)。 wrapper 為了調(diào)用 CGI 程序,還需要一個 FastCGI 的 wrapper(wrapper 可以理解為用于啟動另一個程序的程序),這個 wrapper 綁定在某個固定 socket 上,如端口或者文件 socket。當(dāng) Nginx 將 CGI 請求發(fā)送給這個 socket 的時候,通過 FastCGI 接口,wrapper 接收到請求,然后 Fork(派生)出一個新的線程,這個線程調(diào)用解釋器或者外部程序處理腳本并讀取返回數(shù)據(jù);接著 wrapper 再將返回的數(shù)據(jù)通過 FastCGI 接口,沿著固定的 socket傳遞給 Nginx;最后 Nginx 將返回的數(shù)據(jù)(html 頁面或者圖片)發(fā)送給客戶端。
2、缺省安裝的Nginx+php-fpm環(huán)境
假設(shè)用戶瀏覽一個耗時的網(wǎng)頁,但是卻在服務(wù)端渲染頁面的中途中關(guān)閉了瀏覽器,那么請問服務(wù)端的PHP腳本是繼續(xù)執(zhí)行還是退出執(zhí)行?
答:正常情況下,如果client異常退出了,Server端的程序還是會繼續(xù)執(zhí)行,直到與IO進(jìn)行了兩次交互操作。Server端發(fā)現(xiàn)client端已經(jīng)斷開連接,這個時候會出發(fā)一個User_abort,如果這個沒有設(shè)置ignore_user_abort,那么這個php-fpm的程序才會被中斷。
fpm模塊,對接nginx處理動態(tài)請求,端口9000PHP-FPM(FastCGI Process Manager:FastCGI進(jìn)程管理器)是一個PHPFastCGI管理器,對于PHP 5.3.3之前的php來說,是一個補(bǔ)丁包 [1] ,旨在將FastCGI進(jìn)程管理整合進(jìn)PHP包中。如果你使用的是PHP5.3.3之前的PHP的話,就必須將它patch到你的PHP源代碼中,在編譯安裝PHP后才可以使用。相對Spawn-FCGI,PHP-FPM在CPU和內(nèi)存方面的控制都更勝一籌,而且前者很容易崩潰,必須用crontab進(jìn)行監(jiān)控,而PHP-FPM則沒有這種煩惱。3、已知nginx和php-fpm安裝在同一臺服務(wù)器上,nginx連接php-fpm有兩種方式:一種是類似127.0.0.1:9000的TCP socket,另一種是類似/tmp/php-fpm.sock的Unix domain socket,請問如何選擇?需要注意什么?
Unix domain socket的流程不會走到TCP那層,直接以文件的形式,以stream socket通信。如果是TCP Socket,則需要走到IP層。說的通俗一點(diǎn),追求可靠性就是選擇TCP(需要占用一個端口,更穩(wěn)定,如:127.0.0.1:9000),追求高性能就是Unix Socket(不需要占用端口,更快,但可靠性不如TCP的方式)。
總結(jié)
- 上一篇: Linux(全)
- 下一篇: Nginx 服务优化与防盗链