切圖仔的 Nginx 小書?

切圖仔的 Nginx 小書

本文陸續介紹 Nginx 的功能、配置、及一些實用場景(待完善...)。javascript

1、介紹 Nginx

1. Nginx 是什麼?

Nginx,不少工程師喜歡讀成'恩基克思'。Nginx 是一款高性能的HTTP和反向代理服務器軟件,第一個開源版本誕生於2004年,雖然誕生較晚但通過十多年的發展,已經成爲很是流行的 web 服務器軟件。其發展速度和流行程度已經遠遠超過其它同類軟件,成爲大型網站和高併發網站的首選。php

2. Nginx 爲何流行

Nginx 之因此可以脫穎而出,一方面是由於市場每每會選擇簡單實用的技術,另外一方面是由於web服務器的高併發已經成爲趨勢,而高併發又要求架構具備健壯性和可伸縮性。Nginx 的特性迎合了市場的這個發展趨勢,它是爲性能而生,從發佈以來一直側重於高性能,高併發,低 CPU 內存消耗;在功能方面:負載均衡,反向代理,訪問控制,熱部署,高擴展性等特性又十分適合現代的網絡架構。更難得的是配置簡單文檔豐富,大大下降了學習的門檻。這樣穩定,性能強,功能豐富又簡單的產品固然會受歡迎了。css

3. 爲何選擇 Nginx?

Apache 自1990年發佈以來,一直是 web 服務器市場的霸主。Nginx 雖然發佈較晚,可是卻由於在高併發下卓越的表現而迅速嶄露頭角。最初,Nginx 只是做爲 Apache 在高併發場景下的補充,二者結合輔助使用。而如今,Nginx 隨着迭代功能,在極多數場合已經能夠拋棄老大哥來獨當一面了。html

80端口之爭

Nginx 和 Apache 相同點:前端

  • 同是 Http 服務器軟件,都採用模塊化結構設計
  • 支持通用語言接口,如 PHP,Python 等。
  • 支持正向代理和反向代理。
  • 支持虛擬主機以及 SSL 加密傳輸
  • 支持緩存以及壓縮傳輸
  • 支持 URL 重寫
  • 模塊多,擴展性強
  • 多平臺支持

Nginx 的優點:java

  • 輕量級,安裝簡單、配置文件簡潔,運行時 CPU 內存使用率低。
  • 性能強 支持多核,處理靜態文件效率高。
  • 支持熱部署,啓動速度快,能夠在不間斷服務狀況下對軟件和配置進行升級
  • 負載均衡 支持容錯和健康檢查
  • 代理功能強大 支持無緩存的方向代理,同時支持 IMAP/POPS/SMTP 的代理

Nginx 的劣勢:nginx

  • 相對於老大哥 Apache 模塊要少一些
  • 對動態請求的支持不如 Apache
  • Windows 版本功能有限,受限於 Windows 的特性,支持最好的仍是 *unix 系統

4. Nginx 的工做原理

Nginx 由內核和一系列模塊組成,內核提供 Web Server 的基本功能,如啓動網絡協議,建立運行環境,接收和分配客戶端請求,處理模塊之間的交互。Nginx 的各類功能和操做都由模塊來實現。
Nignx 的模塊從結構上分爲:web

  • 核心模塊:HTTP 模塊、EVENT 模塊和 MAIL 模塊
  • 基礎模塊:HTTP Access 模塊、HTTP FastCGI 模塊、HTTP Proxy 模塊和 HTTP Rewrite 模塊
  • 第三方模塊:HTTP Upstream Request Hash 模塊、Notice 模塊和HTTP Access Key 模塊以及其它自開發模塊。

這樣的設計使 Nginx 方便開發和擴展,也正所以才使得 Nginx 功能如此強大。Nginx 的模塊默認編譯進 Nginx 中,若是須要增長或刪除模塊,須要從新編譯 Nginx ,這一點不如 Apache 的動態模塊加載方便。(若是需動態加載模塊,可使用兼容 Nginx 的web服務器 Tengine )緩存

5. Nginx 的請求處理

Nginx 使用一個多進程模型來應對外來需求,其中一個 master 進程,多個 worker 進程。master 進程負責管理 Nginx 自己和其餘 worker 進程。服務器

全部實際上的業務處理邏輯都在 worker 進程,其內有一個無限循環執行的函數,不斷處理來自客戶端的請求,並進行處理,直到整個 Nginx 服務中止。

worker 進程中,ngx_worker_process_cycle() 就是這個無線循環的函數。內部對一個請求的簡單處理流程以下:

  1. 操做系統提供的機制產生相關的事件
  2. 接受和處理這些事件,若是是接收數據,則產生更高層的request對象
  3. 處理 request 的 header 和 body
  4. 產生響應,併發送回客戶端
  5. 完成 request 的處理
  6. 從新初始化定時器及其餘事件

如圖展現了 Nginx 模塊常規的HTTP請求和響應的過程:
htpp流程

2、Nginx 配置

#運行用戶
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;
        }
 
    }
}

3、Nginx 命令行

不像其餘系統軟件,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

4、Nginx 實用

場景1:適配PC與移動web

通常門戶網站在訪問時,會有 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/  # 手機版  
    }     
}

第三步,由於可能錯誤判斷設備,或者用戶就想指定訪問某種設備版本,在頁面底部,一般會有連接跳轉其餘版本。
foot

<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 參數,則指定進入某個版本。

場景2:前端環境切換

前端開發中,咱們常常須要在多個環境(開發、內測、外測、預發、正式環境)進行切換。
咱們一般經過切換 host 指向搭配機器綁定不一樣域名的方式去實現:好比測試環境是dev.j.esf.sina.com,正式環境是j.esf.sina.com,搭配不一樣的 host 指向,能夠造成多種組合。

而經過反向代理的Nginx,更容易處理這種代理轉發的問題:

  • 咱們經過點擊頁面的環境按鈕,讓綁定的 javascript 代碼往域名下種入帶有 IP 信息的 cookie,同時刷新頁面。
  • Nginx 接收新的請求,讀取請求的 cookie ,若是包含指定的鍵名和值,則代理到這個 IP 地址。(http header 也能夠)
  • 若是沒有,則代理到默認的線上環境。
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;
}

...場景待續

相關文章
相關標籤/搜索