dogken系列----nginx開發

什麼是nginx

  • 2012年成長爲世界第二大web服務器
  • 業內高性能web服務器代名詞
  • 競爭對手
1 Apache
2 Lighttped(受歐美界青睞的,與nginx有的一拼的)
3 Tomcat("java語言web服務器 先天就是重量級性能跟nginx無法比")
4 Jetty("java語言web服務器 先天就是重量級性能跟nginx無法比")
5 IIS(window系統)
複製代碼
  • 基於REST架構風格,以統一資源定位符(URI)貨統一資源描述符(URL)做爲溝通依據
  • 基於事件驅動
  • 高度模塊化的設計----->第三方模塊衆多
  • 可運行在衆多平臺
可使用當前操做系統的高效API來提升本身的性能
支持linux上的epollepoll是大併網絡鏈接的利器
複製代碼

爲何是nginx

1.由於很吊,體如今以下幾個方面

非要用一句話總結,那就是可以支持高併發請求的同時保持高效的服務html

  • 更快 單次請求獲得更快的響應
  • 高擴展性nginx設計極具擴展性,徹底是由多個不一樣層次/不一樣功能/不一樣類型且耦合度極低的模塊組成 而且Nginx的模塊都是嵌入到二進制文件中執行的
-- --好比HTTP模塊中,還設計了HTTP過濾模塊,一個正常的HTTP模塊處理完請求後,會有一連串的HTTP過濾模塊再對其進行過濾。
-- --咱們開發一個新的HTTP模塊時,可使用HTTP核心模塊  events模塊  log模塊等 還能夠自由的複用各類過濾器模塊
複製代碼
  • 高可靠性
  • 低內存消耗
通常狀況下,10000個非活躍的HTTP Keep-Alive鏈接在Nginx中僅消耗2.5M內存
複製代碼
  • 單機支持10萬以上的併發鏈接

前端

理論上,Nginx的併發鏈接數僅取決於內存,10萬遠未封頂,固然與業務特色也緊密相連 複製代碼複製代碼

  • 熱部署
因爲master管理進程與worker工做進程的分離設計
使得nginx能夠不中止服務就能升級可執行文件/更新配置項目/更換日誌文件等
複製代碼
  • nginx的架構設計很高明

java

先天的事件驅動型設計 全異步的網絡I/O處理機制 極少的進程間切換 複製代碼複製代碼

  • 強大的開源社區 數以萬計的碼畜們爲nginx添磚加瓦
2.爲何這麼吊

這裏咱們着重講解一下nginx使用的事件驅動架構,簡單來講以下所示node

產生事件
分發事件
事件發生源
事件收集器收集
時件處理器註冊本身感興趣的事件並消費之

事件源: 通常由網卡和磁盤產生linux

事件收集器: nginx的事件模塊,如ngx_epoll_modulenginx

消費者: 全部其它模塊web

消費者首先向事件模塊註冊本身感興趣的事件類型,當該類型事件產生時,事件模塊就會把事件分發到相應消費者模塊複製代碼

nginx採用徹底的事件驅動架構來處理業務,那它與傳統的web服務器有哪些不一樣呢?apache

  • 傳統web服務器(好比Apache)
    • Apache採用的所謂事件驅動僅僅是體如今TCP鏈接的創建和關閉事件上
      • 一個鏈接創建之後到關閉以前,全部的操做再也不是事件操做,退化成了按序執行每一個操做
      • 整個請求在鏈接期間始終佔用cpu 內存資源,及時沒有做任何有意義的事
      • 把一個進程或線程做爲事件消費者,當一個請求產生事件被該進程處理時,直到請求處理結束時進程資源都將被這一個請求佔用
  • nginx服務器
    • 不會使用進程或者線程做爲事件消費者,所謂的事件消費者只能是某個模塊(在這裏沒有進程的概念)
    • 只有事件收集和分發器纔有資格佔用進程資源
  • 重要差異
    • 前者是每一個事件消費者獨佔一個進程資源,後者的事件消費者只是被事件分發者進程短時間調用而已
  • nginx這種設計的一個弊端
    • 即每一個事件消費者都不能有阻塞行爲,不然會長時間佔用事件分發者進程而致使其它事件得不到及時響應,尤爲是每一個消費者不可讓進程轉爲休眠或等待狀態,這都增長了碼畜們的開發難度

手摸手教你使用nginx

準備工做

安裝nginx開發所需的最基本的庫 如下是完成web服務器功能所須要的基本包安全

  1. 使用uname -a 查看linuxe內核是否時2.6及以上版本

    由於只有linux2.6及以上版本才支持epoll,可以更大限度發揮nginx的威力服務器

  2. GCC編譯器 使用yum install -y gcc安裝

    GCC(GNU Compile Collection)能夠用來編譯C語言程序,由於有時候nginx不會直接提供二進制可執行程序,須要本身編譯

  3. PCRE庫

    Perl正則兼容表達式包,pcre-devel時PCRE作二次開發時所須要的開發庫,也是nginx開發所必需的

  4. zlib庫 yum install -y gzip gzip-devel

    nginx.conf中配置了gzip on對Http 包的內容做gzip格式壓縮,須要用 zlip-devel是二次開發所須要的庫

  5. OpenSSL庫 yum install -y openssl openssl-devel

    若是想使用更安全的SSL 協議傳輸HTTP,就須要該包,若是要使用MD5或者SHA1包,也須要Openssl包

須要瞭解的幾個目錄

  1. nginx源碼存放目錄,隨便放,沒人管你,看我的癖好
  2. Nginx編譯階段產生的中間目錄
該目錄用於存放configuremake命令執行後,生成的中間目錄,默認狀況下,生產objs目錄存放在源碼目錄中
複製代碼
  1. 部署目錄默認 /usr/local/nginx
存放nginx運行期間所需的二進制文件,配置文件等。
複製代碼
  1. 日誌文件存放目錄
若是你要研究nginx的底層架構,那麼打開debug級別日誌後,會產生大量日誌,因此最好弄一個大點的磁盤
複製代碼
源碼編譯安裝
  • 官方下載nginx源碼並解壓後,cd到源碼目錄 ./configure && make && make install
    • 下面咱們來看看這幾個命令作了哪些見不得人的勾當

1 大部分工做其實都是configure命令作了,使用config --help來查看都是有哪些命令 咱們通常只關心如下幾個 2 --prefix=PATH 安裝目錄,默認是/usr/local/nginx --sbin-path=PATH可執行文件防止路徑,默認是?<prefix>/sbin/nginx --conf-path=PATH配置文件路徑,默認是<prefix>/conf/nginx.conf --error-log-path=PATH錯誤日誌文件,默認<prefix>/logs/error.log 後面會在nginx.conf中詳細介紹把不一樣請求的錯誤日誌打到不一樣的log文件中 --pid-path=PATH pid文件存放目錄,默認<prefix>/logs/nginx.pid 這個文件以ascii碼存放着nginx master的進程id

更多的請自行搜索~~~~

複製代碼複製代碼
必須知道的命令

/usr/local/nginx/sbin/nginx命令 默認加載/usr/local/nginx/conf/nginx.conf

/usr/local/nginx/sbin/nginx -c <配置文件目錄>    來啓動非默認的配置
/usr/local/nginx/sbin/nginx -p <目錄>           來指定nginx的安裝目錄 
/usr/local/nginx/sbin/nginx -g 來臨時指定一些全局配置項
    /usr/local/nginx/sbin/nginx -g "pid /var/nginx/test.pid;"
    意味着把pid寫到另外一個文件中,-g指定的不能與默認衝突,另外以-g啓動的ngix在中止事也須要加上-g
    /usr/local/nginx/sbin/nginx -g "pid /var/nginx/test.pid;" -s stop.  若是不加-g 就找不到pid文件了複製代碼

/usr/local/nginx/sbin/nginx -t 不啓動nginx狀況下,測試配置文件將是否有誤

/usr/local/nginx/sbin/nginx -V 顯示版本信息

/usr/local/nginx/sbin/nginx -s stop 快速中止服務處理完當前正在處理的請求後,關閉服務

/usr/local/nginx/sbin/nginx -s reload 運行中的nginx從新加載nginix.conf 等效於kill -s SIGHUP <nginx master pid>

/usr/local/nginx/sbin/nginx -s reopen 等效於kill -s SIGUSR1 <nginx master pid> 能夠從新打開配置文件,這樣咱們就能夠把當前的日誌文件更名或者移動,使其不會太大

平滑升級nginx

1.kill -s SIGUSR2 <nginx master pid> 會將nginx.pid重命名爲nginx.pid.oldbin

2.使用命令啓動nginx

3.使用kill -s SIGQUIT <舊版本的master pid> 關閉舊版本服務

nginx配置
1 生產環境通常都是一個master進程管理多個worker進程,worker進程與cpu核心數相等,每一個worker都能繁忙的提供服務處理。
2 master進程只負責worker的管理。worker進程之間經過共享內存,原子操做等進程間通訊機制實現負載均衡等功能
3 nginx是支持單進程 (只有一個master)提供服務的。使用master+worker的優點以下
    1master只提供純管理工做,只提供命令行服務。
    2worker進程能夠提升服務的健壯型,能夠充分利用多核cpu
複製代碼

爲何須要把nginx的worker 進程數量設置的根cpu核心數一致呢

  1. 在apache上每一個進程每一時刻只能處理一個請求,所以要想併發處理更多的併發請求數就要設置不少個進程,而大量的進程間切換很消耗內存資源
  2. 而nginx的一個worker進程處理的請求數只受限於內存大小,而且worker進程之間處理併發請求時幾乎沒有同步鎖的限制,worker進程也不會進入睡眠狀態,所以當nginx進程與cpu核數一致時(最好每個worker綁定一個內核),進程切換的代價是最小的
  3. 將進程與cpu綁定,這樣不會出現多個進程搶佔一個cpu的問題,就不會出現同步問題,這樣在內核的調度上就實現了徹底的併發

nginx.conf文件說明 nginx的配置文件採用塊配置項的組織方式,以下所示

全局配置
塊配置項名1 {
 配置項名 配置項值1 配置項值1;
}
塊配置項名2  參數 {
 配置項名 配置項值1 配置項值1;
}
基本的塊配置項有:events  http  server  location  upstreams  快配置項能夠嵌套
配置項名必須是nginx的某一個配置模塊中想要處理的,不然會出錯
若是配置項值中包括語法符號,好比空格,須要用引號括注配置項值 ========
配置項的單位,若是是空間大小是 k或者m
有些模塊容許配置項值中使用變量,變量前加上$ ======
複製代碼

一個具體的nginx.conf配置說明以下可能包括如下幾部分,這裏我儘量多的寫幾個哈~方便本身之後回頭查閱

  • 全局配置

    • user username [groupname];
      • 用於當master進程啓動後,fork出的worker進程運行在哪一個用戶和用戶組下
      • 須要在configure時使用參數 --user=username --group=groupname
    • daemo on|off; 是否以守護進程方式運行服務,默認on
    • master_process on|off; 是否以master/worker方式工做 默認on
    • error_log /path/file level; 錯誤日誌 默認logs/error.log error
      • 能夠是/dev/null,這樣就不會有任何日誌了,這也是關閉error日誌的惟一手段了
      • 若是日誌級別寫成debug,那麼在最初configure時須要加上--with-debug配置項
    • woker_rlimit_nofile limit; 一個worker進程能夠打開的最大句柄描述符個數
    • worker_rlimit_core size;
    • worker_directory path;
      • 當進程意外終止時,nginx會把進程執行時的內存內容轉儲到一個core文件中,方便咱們查看寄存器堆棧來定位問題,上面兩個配置設定這個文件的大小和目錄
    • env VAR|VAR=VALUE 這個配置項可讓用戶直接操做系統變量
    • include /path/file
      • 將其它配置文件嵌入到nginx.conf中,它的目錄能夠是絕對的,也能夠是相對的,相對nginx.conf所在目錄
    • worker_process 4;
    • worder_cpu_affinity 1000 0100 0010 0001
      • 上面兩個配置將worder進程與cpu實現綁定
    • worker_priority nice nginx 的進程優先級配置s
  • 事件類配置

    events {

    debug_connection IP;  只對該ip的請求才輸出debug級別的日誌,能夠經過該方法定位bug
    accept_mutex [on|off]; 負載均衡鎖,默認打開,若是關閉創建TCP連接的耗時更短,但每一個worker的負載會很是不均衡
    lock_file path/file;  accept鎖須要這個文件,若是因爲程序的編譯和操做系統的架構等因素致使nginx不支持原子鎖, 就會用文件鎖來實現accept鎖。若是支持原子鎖,這個文件就沒意義了
    accept_mutex_delay Nms; 使用文件鎖後,同一時間只有一個worker能得到到這個鎖,這個鎖不是阻塞所,worker獲取不到,會當即返回,而後間隔這個時間以後再去獲取。
    multi_accept on|off;默認關閉,當事件模型通知有新鏈接時,儘量的對本次調度中客戶端發起的全部的TCP請求都去創建鏈接
    use [poll| select | epoll| kqueue]; Nginx 默認會選擇最合適的事件模型
    woker_connections  number; 每一個worker進程能夠同時處理的最大鏈接數
    複製代碼

    }

  • http模塊

    靜態web服務器主要由nginx中的ngx_http_core_module實現 http模塊是一個最小靜態web服務器的基本配置

    http {

    gzip on; server { listen address:port; address能夠是ip或者hostname port後能夠加上一些參數 以下所示 listen 443 default_server ssl deferred; deault_server當一個請求沒法匹配全部的域名後,使用這個做爲默認處理域名 ssl 在當前端口的鏈接必須是基於SSL協議 deferred用戶發起創建鏈接請求,完成TCP三次握手以後,內核也不會調度worker進程來處理此次連接, 只有用戶真的發了數據(網卡收到請求數據包)內核纔會喚醒worker進程去處理, server_name name ;後面能夠跟多個主機名稱,用頓號隔開 'nginx 收到請求後,會先取出Header頭中的host,根server中去比較,若是匹配了多個server,會根據匹配優先級來選擇用哪一個server, 若是都找不到,就用server_name 爲空的server' server_name_in_redirect on|off 默認爲on '若是爲開啓,那麼首先查找server_name,若是沒有找到,查找請求頭的HOST字段,若是沒有,則以當前服務器的IP進行拼接 location [=|~|~*|^~|@] /uri/ {} uri參數裏能夠用正則 location = / {} 用戶請求是/時匹配 URI大小寫敏感 ~* 匹配URI時忽略大小寫 ^~前半部分大小寫敏感匹配,如 location ^~ /images/ {}/images/ 開始的請求都會匹配 @表示nginx內部請求之間的重定向,不直接處理用戶請求 root path 文件路徑,默認是root html root配置還能夠位於http模塊下或者location下,若是位於location下含義以下 location /download/ { root /opt/web/html/; } 若是用戶的請求是/download/test.html,web服務器將會返回服務器上的/opt/web/html/download/test.html文件中內容 location /conf { location下配置說明 alias /usr/local/nginx/conf/ 若是用戶請求是/conf/nginx.conf,用戶實際想訪問/usr/local/nginx/conf/nginx.conf,就可使用alias配置 alias只能放在location root path; index 首頁文件; } error_page code uri|@named_location 也能夠在location塊中配置 能夠做以下配置 error_code 404 /404.html error_code 501 502 504 /50x.html error_code 403 http://example.com/forbidden.html error_code 404 = @fetch 也能夠改變錯誤碼 error_page 404 =200 /empty.gif 或者不指定錯誤碼 ,由重定向後的實際處理決定 error_page 404 /empty.gif 若是不想修改uri,只是想定向到另外一個location中處理,能夠以下配置 location / { error_code 404 @fallback }
            <span class="hljs-keyword">location</span> <span class="hljs-title">@fallback</span> {
                proxy_pass http://backend;
            }
    try_files path1 path2 uri <span class="zh-hans">嘗試訪問每個</span>path<span class="zh-hans">找到了就結束請求</span> <span class="zh-hans">,都找不到久落到了</span>uri<span class="zh-hans">上</span>,<span class="zh-hans">因此</span>uri<span class="zh-hans">必須存在</span>
    <span class="hljs-keyword">type</span> {  MIME<span class="zh-hans">類型設置</span>,<span class="zh-hans">能夠位於</span>server location<span class="zh-hans">塊中</span>
        <span class="hljs-keyword">type</span><span class="zh-hans">說白了就是不一樣的文件類型用不一樣的應用程序打開。</span>
    }
    複製代碼
    複製代碼<span class="hljs-keyword">location</span> <span class="hljs-title">@fallback</span> { proxy_pass http://backend; } try_files path1 path2 uri <span class="zh-hans">嘗試訪問每個</span>path<span class="zh-hans">找到了就結束請求</span> <span class="zh-hans">,都找不到久落到了</span>uri<span class="zh-hans">上</span>,<span class="zh-hans">因此</span>uri<span class="zh-hans">必須存在</span> <span class="hljs-keyword">type</span> { MIME<span class="zh-hans">類型設置</span>,<span class="zh-hans">能夠位於</span>server location<span class="zh-hans">塊中</span> <span class="hljs-keyword">type</span><span class="zh-hans">說白了就是不一樣的文件類型用不一樣的應用程序打開。</span> } 複製代碼} "http中還有賊多的配置 好比tcp網絡連接 內存資源管理 對客戶端請求的限制 文件操做的優化等等,等用到了能夠具體研究" 複製代碼

    }

    反向代理服務器配置

nginx的高併發高負載能力至關彪悍,通常能夠直接做爲web服務器向用戶提供靜態文件服務。但有些複雜業務不適合直接放在nginx服務器上,這時候會用Apache等服務器來處理,使用nginx做爲靜態web服務器和反反向代理服務器,不適合nginx處理的請求直接轉到上游服務器處理

nginx反向代理方式

HTTP請求--->nginx將請求內容落地到所在服務器硬盤或內存---->向上遊服務器發起鏈接複製代碼
  • 優勢:下降上游業務服務器的負載,儘可能把壓力放在nginx服務器上
    • 由於客戶端與代理服務器之間走公網,網絡環境複雜,而代理服務器與上游業務服務器走的是內部專網,在接收完用戶請求後,在內網轉發會至關快。若是是一邊接收一邊轉發,外網的爛速度就會拖垮內網。
  • 缺點: 延長了請求處理時間,增長了nginx服務器的內存和磁盤空間

負載均衡配置在http模塊中

http {

upstream backen {
    ip_hash;
    server backend1.example.com  weight=5;
    server backend2.example.com  max_failes3  fail_timeout=30s;
}
    #定義了一個叫做backend的上游服務器集羣
    #server 後能夠跟域名 IP地址端口等
    #weight轉發權重
    #max_failem默認爲1,0表示不檢查失敗次數;faile_timeout默認爲10s   30s內轉發失敗3次,認爲該服務器不可用
    #ip_hash保證同一個ip的請求落到同一個服務器上,不能與weight同時使用,
    而且若是服務器集羣中有一臺機器掛掉,不能直接刪除該配置, 而要使用down進行標示,以保證轉發策略的一致性
    #反向代理還提供了一些變量如:$remote_addr $time_local  $request 等等 能夠在access_loglog_format日誌格式配置中使用???
複製代碼

}

反向代理配置在location模塊中,配置以下

upstream backen { ..... } 複製代碼server{ location /{ proxy_pass http://backend; proxy_set_header Host $host #默認狀況反向代理是不會轉發請求中的host頭部,若是須要轉發,使用proxy_set_header配置 } } 複製代碼

nginx進階

相關文章
相關標籤/搜索