本文陸續介紹 Nginx 的功能、配置、及一些實用場景(待完善...)。javascript
Nginx,不少工程師喜歡讀成'恩基克思'。Nginx 是一款高性能的HTTP和反向代理服務器軟件,第一個開源版本誕生於2004年,雖然誕生較晚但通過十多年的發展,已經成爲很是流行的 web 服務器軟件。其發展速度和流行程度已經遠遠超過其它同類軟件,成爲大型網站和高併發網站的首選。php
Nginx 之因此可以脫穎而出,一方面是由於市場每每會選擇簡單實用的技術,另外一方面是由於web服務器的高併發已經成爲趨勢,而高併發又要求架構具備健壯性和可伸縮性。Nginx 的特性迎合了市場的這個發展趨勢,它是爲性能而生,從發佈以來一直側重於高性能,高併發,低 CPU 內存消耗;在功能方面:負載均衡,反向代理,訪問控制,熱部署,高擴展性等特性又十分適合現代的網絡架構。更難得的是配置簡單文檔豐富,大大下降了學習的門檻。這樣穩定,性能強,功能豐富又簡單的產品固然會受歡迎了。css
Apache 自1990年發佈以來,一直是 web 服務器市場的霸主。Nginx 雖然發佈較晚,可是卻由於在高併發下卓越的表現而迅速嶄露頭角。最初,Nginx 只是做爲 Apache 在高併發場景下的補充,二者結合輔助使用。而如今,Nginx 隨着迭代功能,在極多數場合已經能夠拋棄老大哥來獨當一面了。html
Nginx 和 Apache 相同點:前端
Nginx 的優點:java
Nginx 的劣勢:nginx
Nginx 由內核和一系列模塊組成,內核提供 Web Server 的基本功能,如啓動網絡協議,建立運行環境,接收和分配客戶端請求,處理模塊之間的交互。Nginx 的各類功能和操做都由模塊來實現。
Nignx 的模塊從結構上分爲:web
這樣的設計使 Nginx 方便開發和擴展,也正所以才使得 Nginx 功能如此強大。Nginx 的模塊默認編譯進 Nginx 中,若是須要增長或刪除模塊,須要從新編譯 Nginx ,這一點不如 Apache 的動態模塊加載方便。(若是需動態加載模塊,可使用兼容 Nginx 的web服務器 Tengine )緩存
Nginx 使用一個多進程模型來應對外來需求,其中一個 master 進程,多個 worker 進程。master 進程負責管理 Nginx 自己和其餘 worker 進程。服務器
全部實際上的業務處理邏輯都在 worker 進程,其內有一個無限循環執行的函數,不斷處理來自客戶端的請求,並進行處理,直到整個 Nginx 服務中止。
worker 進程中,ngx_worker_process_cycle() 就是這個無線循環的函數。內部對一個請求的簡單處理流程以下:
如圖展現了 Nginx 模塊常規的HTTP請求和響應的過程:
#運行用戶 user nobody; #啓動進程,一般設置成和cpu的數量相等 worker_processes 1; #全局錯誤日誌及PID文件 #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; #工做模式及鏈接數上限 events { #單個後臺worker process進程的最大併發連接數 worker_connections 1024; } http { #設定mime類型,類型由mime.type文件定義 include 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"'; access_log logs/access.log main; #sendfile 指令指定 nginx 是否調用 sendfile 函數(zero copy 方式)來輸出文件, #對於普通應用,必須設爲 on, #若是用來進行下載等應用磁盤IO重負載應用,可設置爲 off, #以平衡磁盤與網絡I/O處理速度,下降系統的uptime. sendfile on; #tcp_nopush on; #鏈接超時時間 #keepalive_timeout 0; keepalive_timeout 65; #開啓gzip壓縮 #gzip off; #設定虛擬主機配置 server { #偵聽80端口 listen 80; #定義使用 www.nginx.cn訪問 server_name www.nginx.cn; #定義服務器的默認網站根目錄位置 root html; #設定本虛擬主機的訪問日誌 access_log logs/nginx.access.log main; #默認請求 location / { #定義首頁索引文件的名稱 index index.php index.html index.htm; } # 定義錯誤提示頁面 error_page 500 502 503 504 /50x.html; location = /50x.html { } #靜態文件,nginx本身處理 location ~ ^/(images|javascript|js|css|flash|media|static)/ { #過時30天,靜態文件不怎麼更新,過時能夠設大一點, #若是頻繁更新,則能夠設置得小一點。 expires 30d; } #PHP 腳本請求所有轉發到 FastCGI處理. 使用FastCGI默認配置. location ~ .php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } #禁止訪問 .htxxx 文件 location ~ /.ht { deny all; } } }
不像其餘系統軟件,Nginx 僅由幾個命令行參數
-c </path/to/config> // 爲Nginx指定一個配置文件,來代替缺省的 -t // 不運行,僅僅測試配置。 -v // 顯示Nginx的版本 -V // 顯示Nginx的版本,編譯器版本和配置參數。
Nginx 啓動、中止、重啓命令
// 啓動 sudo nginx // 或者 sudo /usr/local/Cellar/nginx/1.12.0_1/bin/nginx // 若是不知道實際路徑,能夠nginx —V查看 // 中止命令 ps -ef | grep nginx // 查看佔用進程 kill -QUIT nginx主進程號 // 從容中止 kill -TERM nginx主進程號 // 快速中止 kill -9 nginx主進程號 // 強制中止 // 或者 kill -QUIT `cat /usr/local/var/run/nginx.pid` // 若是不知道實際路徑,能夠nginx —V查看 // 重啓命令 kill -QUIT `cat /usr/local/var/run/nginx.pid` sudo /usr/local/Cellar/nginx/1.12.0_1/bin/nginx
通常門戶網站在訪問時,會有 PC 和 H五、Pad 幾個適配版本,咱們常會有這樣的需求,在網站被訪問時候,服務端來識別用戶是 PC 設備仍是移動設備,跳轉返回相應適配版本的頁面。
第一步一般是判斷 HTTP 請求頭的 User-Agent ,基本原理是經過正則匹配判斷,有一套開源的解決方案能夠直接使用:http://detectmobilebrowsers.com/,下載 Nginx 配置便可。
第二步就是經過以前對設備的判斷,來反向代理到不一樣的版本。
location / { proxy_pass http://leju.com if ($mobile_rewrite = perform) { proxy_pass http://m.leju.com/ # 手機版 } }
第三步,由於可能錯誤判斷設備,或者用戶就想指定訪問某種設備版本,在頁面底部,一般會有連接跳轉其餘版本。
<div class="ll_btn"> <a href="http://www.leju.com#ln=index_fdh">電腦版</a> <a href="http://pad.leju.com/?source=chuping#ln=index_fdh">PAD版</a> <a href="http://m.leju.com/touch/app/app_download.html?source=chupinghp#ln=index_fdh">客戶端</a> </div>
同時在 Nginx 中加入判斷,若是包含指定 source 參數,則指定進入某個版本。
前端開發中,咱們常常須要在多個環境(開發、內測、外測、預發、正式環境)進行切換。
咱們一般經過切換 host 指向搭配機器綁定不一樣域名的方式去實現:好比測試環境是dev.j.esf.sina.com
,正式環境是j.esf.sina.com
,搭配不一樣的 host 指向,能夠造成多種組合。
而經過反向代理的Nginx,更容易處理這種代理轉發的問題:
set $env_id 「123.59.190.206」; if( $http_cookie~* "host_id(\S+)(;.*|$)"){ set $env_id $1; } location / { proxy_set_header Host $host; proxy_pass http://$env_id:80; }
...場景待續