精通Nginx(一)

博文參考

http://www.cnblogs.com/wylhome/p/6057198.html
http://tengine.taobao.org/book/chapter_02.html
http://blog.csdn.net/justin_yaphet/article/details/47910439

Nginx:

Nginx (engine x) 是一個高性能的HTTP和反向代理服務器,也是一個IMAP/POP3/SMTP服務器。Nginx是由Igor Sysoev爲俄羅斯訪問量第二的Rambler.ru站點開發的,第一個公開版本0.1.0發佈於2004年10月4日。其將源代碼以類BSD許可證的形式發佈,因它的穩定性、豐富的功能集、示例配置文件和低系統資源的消耗而聞名。 html

Nginx是一款輕量級的Web 服務器/反向代理服務器及電子郵件(IMAP/POP3)代理服務器,並在一個BSD-like協議下發行。由俄羅斯的程序設計師Igor Sysoev所開發,供俄國大型的入口網站及搜索引擎Rambler使用。其特色是佔有內存少,併發能力強,事實上nginx的併發能力確實在同類型的網頁服務器中表現較好,中國大陸使用nginx網站用戶有:百度、京東、新浪、網易、騰訊、淘寶等。 前端

Nginx能夠在大多數 UnixLinux OS上編譯運行,並有Windows移植版。 Nginx 的1.4.0穩定版已經於2013年4月24日發佈,2016年10月18日,Nginx1.10.2 穩定版本發佈。通常狀況下,對於新建站點,建議使用最新穩定版做爲生產版本,已有站點的升級急迫性不高。Nginx 的源代碼使用2-clause BSD-like license。linux

代理服務器:

通常是指局域網內部的機器經過代理服務器發送請求到互聯網上的服務器,代理服務器通常做用在客戶端。 nginx

clipboard.png
一個完整的代理請求過程爲:客戶端首先與代理服務器建立鏈接,接着根據代理服務器所使用的代理協議,請求對目標服務器建立鏈接、或者得到目標服務器的指定資源。 Web代理(proxy)服務器是網絡的中間實體。 代理位於Web客戶端和Web服務器之間,扮演「中間人」的角色。HTTP的代理服務器便是Web服務器又是Web客戶端。 web

代理服務器是介於客戶端和Web服務器之間的另外一臺服務器,有了它以後,瀏覽器不是直接到Web服務器去取回網頁而是向代理服務器發出請求,信號會先送到代理服務器,由代理服務器來取回瀏覽器所須要的信息並傳送給你的瀏覽器。apache

正向代理:

是一個位於客戶端和原始服務器(origin server)之間的服務器,爲了從原始服務器取得內容,客戶端向代理髮送一個請求並指定目標(原始服務器),而後代理向原始服務器轉交請求並將得到的內容返回給客戶端。客戶端必需要進行一些特別的設置才能使用正向代理。編程

反向代理服務器:

在服務器端接受客戶端的請求,而後把請求分發給具體的服務器進行處理,而後再將服務器的響應結果反饋給客戶端。Nginx就是其中的一種反向代理服務器軟件。 vim

說明:客戶端必須設置正向代理服務器,固然前提是要知道正向代理服務器的IP地址,還有代理程序的端口。 後端

反向代理正好與正向代理相反,對於客戶端而言代理服務器就像是原始服務器,而且客戶端不須要進行任何特別的設置。客戶端向反向代理的命名空間(name-space)中的內容發送普通請求,接着反向代理將判斷向何處(原始服務器)轉交請求,並將得到的內容返回給客戶端。
圖片描述
用戶A始終認爲它訪問的是原始服務器B而不是代理服務器Z,但實用際上反向代理服務器接受用戶A的應答,從原始資源服務器B中取得用戶A的需求資源,而後發送給用戶A。因爲防火牆的做用,只容許代理服務器Z訪問原始資源服務器B。儘管在這個虛擬的環境下,防火牆和反向代理的共同做用保護了原始資源服務器B,但用戶A並不知情。centos

Nginx特色:

跨平臺:Nginx 能夠在大多數 Unix like OS編譯運行,並且也有Windows的移植版本。

配置異常簡單:很是容易上手。配置風格跟程序開發同樣,神通常的配置

非阻塞、高併發鏈接:數據複製時,磁盤I/O的第一階段是非阻塞的。官方測試可以支撐5萬併發鏈接,在實際生產環境中跑到2~3萬併發鏈接數.(這得益於Nginx使用了最新的epoll模型)

事件驅動:通訊機制採用epoll模型,支持更大的併發鏈接。

Nginx優勢:

高併發:Nginx 是一個很強大的高性能Web和反向代理服務器,它具備不少很是優越的特性。在鏈接高併發的狀況下,Nginx是Apache服務器不錯的替代品,可以支持高達 50,000 個併發鏈接數的響應。

clipboard.png

負載均衡器:Nginx做爲負載均衡服務器:Nginx 既能夠在內部直接支持 Rails 和 PHP 程序對外進行服務,也能夠支持做爲 HTTP代理服務器對外進行服務。
圖片描述

代理服務器:Nginx自己就是一個反向代理服務器,可支持郵件服務器代理以及http代理
圖片描述

Nginx相比Apache:

1.輕量級,一樣起web 服務,比apache 佔用更少的內存及資源

2.抗併發,nginx 處理請求是異步非阻塞的,而apache 則是阻塞型的,在高併發下nginx 能保持低資源低消耗高性能

3.高度模塊化的設計,編寫模塊相對簡單

4.配置簡潔易懂,正則配置讓不少事情變得簡單

Nginx事件處理機制:

對於一個基本的web服務器來講,事件一般有三種類型,網絡事件、信號、定時器。

首先看一個請求的基本過程:創建鏈接—接收數據—發送數據 。

再次看系統底層的操做 :上述過程(創建鏈接—接收數據—發送數據)在系統底層就是讀寫事件。

(1)若是採用阻塞調用的方式,當讀寫事件沒有準備好時,必然不可以進行讀寫事件,那麼久只好等待,等事件準備好了,才能進行讀寫事件。那麼請求就會被耽擱 。阻塞調用會進入內核等待,cpu就會讓出去給別人用了,對單線程的worker來講,顯然不合適,當網絡事件越多時,你們都在等待呢,cpu空閒下來沒人用,cpu利用率天然上不去了,更別談高併發了 。

(2)既然沒有準備好阻塞調用不行,那麼採用非阻塞方式。非阻塞就是,事件,立刻返回EAGAIN, 告訴你,事件還沒準備好呢,你慌什麼,過會再來吧。好吧,你過一會,再來檢查一下事件,直到事件準備好了爲止,在這期間,你就能夠先去作其它事情,而後再 來看看事件好了沒。雖然不阻塞了,但你得不時地過來檢查一下事件的狀態,你能夠作更多的事情了,但帶來的開銷也是不小的

小結:非阻塞經過不斷檢查事件的狀態來判斷是否進行讀寫操做,這樣帶來的開銷很大。

(3)所以纔有了異步非阻塞的事件處理機制。具體到系統調用就是像select/poll/epoll/kqueue這樣的系統調用。他們提供了一種機制,讓你能夠同時監控多個事件,調用他們是阻塞的,但能夠設置超時時間,在超時時間以內,若是有事件準備好了,就返回。這種機制解決了咱們上面兩個問題。

以epoll爲例:當事件沒有準備好時,就放入epoll(隊列)裏面。若是有事件準備好了,那麼就去處理;若是事件返回的是EAGAIN,那麼繼續將其放入epoll裏面。從而,只要有事件準備好了,咱們就去處理她,只有當全部時間都沒有準備好時,纔在epoll裏 面等着。這樣,咱們就能夠併發處理大量的併發了,固然,這裏的併發請求,是指未處理完的請求,線程只有一個,因此同時能處理的請求固然只有一個了,只是在 請求間進行不斷地切換而已,切換也是由於異步事件未準備好,而主動讓出的。這裏的切換是沒有任何代價,能夠理解爲循環處理多個準備好的事件

(4)與多線程的比較:

與多線程相比,這種事件處理方式是有很大的優點的,不須要建立線程,每一個請求佔用的內存也不多,沒有上下文切換,事件處理很是的輕量級。併發數再多也不會致使無謂的資源浪費(上下文切換)。

小結:經過異步非阻塞的事件處理機制,Nginx實現由進程循環處理多個準備好的事件,從而實現高併發和輕量級。

master/worker結構:一個master進程,生成一個或多個worker進程

內存消耗小:處理大併發的請求內存消耗很是小。在3萬併發鏈接下,開啓的10個Nginx 進程才消耗150M內存(15M*10=150M) 成本低廉:Nginx爲開源軟件,能夠無償使用。而購買F5 BIG-IP、NetScaler等硬件負載均衡交換機則須要十多萬至幾十萬人民幣

內置的健康檢查功能:若是 Nginx Proxy 後端的某臺 Web 服務器宕機了,不會影響前端訪問。

節省帶寬:支持 GZIP 壓縮,能夠添加瀏覽器本地緩存的 Header 頭。

穩定性高:用於反向代理,宕機的機率微乎其微。

Nginx架構:

Nginx在啓動後,在Unix系統中會以daemon的方式在後臺運行,後臺進程包含一個master進程和多個worker進程。咱們也能夠手動地關掉後臺模式,讓Nginx在前臺運行,而且經過配置讓Nginx取消master進程,從而可使Nginx以單進程方式運行。很顯然,生產環境下咱們確定不會這麼作,因此關閉後臺模式,通常是用來調試用的,Nginx是以多進程的方式來工做的,固然Nginx也是支持多線程的方式的,只是咱們主流的方式仍是多進程的方式,也是Nginx的默認方式。Nginx採用多進程的方式有諸多好處。

Nginx在啓動後,會有一個master進程和多個worker進程。master進程主要用來管理worker進程,包含:接收來自外界的信號,向各worker進程發送信號,監控worker進程的運行狀態,當worker進程退出後(異常狀況下),會自動從新啓動新的worker進程。而基本的網絡事件,則是放在worker進程中來處理了。多個worker進程之間是對等的,他們同等競爭來自客戶端的請求,各進程互相之間是獨立的。一個請求,只可能在一個worker進程中處理,一個worker進程,不可能處理其它進程的請求。worker進程的個數是能夠設置的,通常咱們會設置與機器cpu核數一致,這裏面的緣由與Nginx的進程模型以及事件處理模型是分不開的。Nginx的進程模型,能夠由下圖來表示:

clipboard.png

master進程會接收來自外界發來的信號,再根據信號作不一樣的事情。因此咱們要控制Nginx,只須要經過kill向master進程發送信號就好了。好比kill -HUP pid,則是告訴Nginx,從容地重啓Nginx,咱們通常用這個信號來重啓Nginx,或從新加載配置,由於是從容地重啓,所以服務是不中斷的。master進程在接收到HUP信號後是怎麼作的呢?首先master進程在接到信號後,會先從新加載配置文件,而後再啓動新的worker進程,並向全部老的worker進程發送信號,告訴他們能夠光榮退休了。新的worker在啓動後,就開始接收新的請求,而老的worker在收到來自master的信號後,就再也不接收新的請求,而且在當前進程中的全部未處理完的請求處理完成後,再退出。固然,直接給master進程發送信號,這是比較老的操做方式,Nginx在0.8版本以後,引入了一系列命令行參數,來方便咱們管理。好比,./nginx -s reload,就是來重啓Nginx,./nginx -s stop,就是來中止Nginx的運行。如何作到的呢?咱們仍是拿reload來講,咱們看到,執行命令時,咱們是啓動一個新的Nginx進程,而新的Nginx進程在解析到reload參數後,就知道咱們的目的是控制Nginx來從新加載配置文件了,它會向master進程發送信號,而後接下來的動做,就和咱們直接向master進程發送信號同樣了。

worker進程之間是平等的,每一個進程,處理請求的機會也是同樣的。當咱們提供80端口的http服務時,一個鏈接請求過來,每一個進程都有可能處理這個鏈接。每一個worker進程都是從master進程fork過來,在master進程裏面,先創建好須要listen的socket(listenfd)以後,而後再fork出多個worker進程。全部worker進程的listenfd會在新鏈接到來時變得可讀,爲保證只有一個進程處理該鏈接,全部worker進程在註冊listenfd讀事件前搶accept_mutex,搶到互斥鎖的那個進程註冊listenfd讀事件,在讀事件裏調用accept接受該鏈接。當一個worker進程在accept這個鏈接以後,就開始讀取請求,解析請求,處理請求,產生數據後,再返回給客戶端,最後才斷開鏈接,這樣一個完整的請求就是這樣的了。一個請求,徹底由worker進程來處理,並且只在一個worker進程中處理。

對於每一個worker進程來講,獨立的進程,不須要加鎖,因此省掉了鎖帶來的開銷,同時在編程以及問題查找時,也會方便不少。其次,採用獨立的進程,可讓互相之間不會影響,一個進程退出後,其它進程還在工做,服務不會中斷,master進程則很快啓動新的worker進程。固然,worker進程的異常退出,確定是程序有bug了,異常退出,會致使當前worker上的全部請求失敗,不過不會影響到全部請求,因此下降了風險。

nginx的模塊化體系結構:

nginx的內部結構是由核心部分和一系列的功能模塊所組成。這樣劃分是爲了使得每一個模塊的功能相對簡單,便於開發,同時也便於對系統進行功能擴展。爲了便於描述,下文中咱們將使用nginx core來稱呼nginx的核心功能部分。

nginx提供了web服務器的基礎功能,同時提供了web服務反向代理,email服務反向代理功能。nginx core實現了底層的通信協議,爲其餘模塊和nginx進程構建了基本的運行時環境,而且構建了其餘各模塊的協做基礎。除此以外,或者說大部分與協議相關的,或者應用相關的功能都是在這些模塊中所實現的。

模塊概述:

nginx將各功能模塊組織成一條鏈,當有請求到達的時候,請求依次通過這條鏈上的部分或者所有模塊,進行處理。每一個模塊實現特定的功能。例如,實現對請求解壓縮的模塊,實現SSI的模塊,實現與上游服務器進行通信的模塊,實現與FastCGI服務進行通信的模塊。

有兩個模塊比較特殊,他們居於nginx core和各功能模塊的中間。這兩個模塊就是http模塊和mail模塊。這2個模塊在nginx core之上實現了另一層抽象,處理與HTTP協議和email相關協議(SMTP/POP3/IMAP)有關的事件,而且確保這些事件能被以正確的順序調用其餘的一些功能模塊。

目前HTTP協議是被實如今http模塊中的,可是有可能未來被剝離到一個單獨的模塊中,以擴展nginx支持SPDY協議。

nginx的請求處理:

nginx使用一個多進程模型來對外提供服務,其中一個master進程,多個worker進程。master進程負責管理nginx自己和其餘worker進程。

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

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

1.操做系統提供的機制(例如epoll, kqueue等)產生相關的事件。

2.接收和處理這些事件,如是接受到數據,則產生更高層的request對象。

3.處理request的header和body。

4.產生響應,併發送回客戶端。

5.完成request的處理。

6.從新初始化定時器及其餘事件。

編譯安裝Nginx:

[root@localhost ~]# yum -y groupinstall "Development Tools" "Server Platform Development" 安裝開發包組
[root@localhost ~]# yum -y install pcre-devel openssl-devel zlib-devel #安裝依賴包
[root@localhost ~]# useradd -r nginx # 建立nginx系統用戶
[root@localhost~]#./configure--prefix=/usr/local/nginx--conf-path=/etc/nginx/nginx.conf--error-log-path=/var/log/nginx/error.log--http-log-path=/var/log/nginx/access.log--pid-path=/var/run/nginx.pid--lock-path=/var/run/nginx.lock --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_dav_module --with-http_stub_status_module --with-threads --with-file-aio # 配置nginx
[root@localhost ~]# make #編譯
[root@localhost ~]# make install  #安裝或設置鏈接官網的yum源(官網地址http://nginx.org/packages/cen...

[root@localhost ~]#vim /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx
baseurl=http://nginx.org/packages/cen...
gpgcheck=0
[root@localhost ~]#yum install nginx
[root@localhost ~]#systemctl start nginx.service

clipboard.png

也可從本地epel直接安裝

[root@localhost ~]#yum install nginx
[root@localhost ~]#systemctl start nginx.service

clipboard.png

修改歡迎頁面

[root@nginx1 /etc/nginx]#mkdir /data/nginx/vhost1 -pv
[root@nginx1 /etc/nginx]#vim /data/nginx/vhost1/index.html
<h1>Nginx Vhost 1</h1>
[root@nginx1 /etc/nginx]#vim conf.d/vhost1.conf
server {

listen 80;#監聽80端口
    server_name www.ilinux.io;#主機名爲www.ilinux.io
    root /data/nginx/vhost1;#路徑

}
[root@nginx1 /etc/nginx]#nginx -t
[root@nginx1 /etc/nginx]#nginx -s reload#重載配置文件
[root@nginx1 /etc/nginx]#vim /etc/hosts
172.16.254.127 www.ilinux.io

clipboard.png

程序環境

配置文件的組成部分:

主配置文件:nginx.conf

include conf.d/*.conf

fastcgi, uwsgi,scgi等協議相關的配置文件

mime.types:支持的mime類型

主程序文件:/usr/sbin/nginx

Unit File:nginx.service

Nginx配置文件:

nginx配置文件組成:主配置文件nginx.conf,conf.d/*.conf;

fastcgi,uwsgi,scgi等協議相關的配置文件;

mime.types:支持的mime類型

main段配置:

分類:

正常運行必備的配置

優化性能相關的配置

用於調試及定位問題相關的配置

事件驅動相關的配置

正常運行必備的配置:

一、user # 指定用於運行worker進程時的用戶

Syntax: user user [group]; 

    Default:user nobody nobody; 

    Context: main

二、pid /PATH/TO/PID_FILE; # 指定存儲nginx主進程進程號碼的文件路徑

Syntax: pid file; 

    Default:pid nginx.pid; 

    Context:main

三、include file | mask; # 指明包含進來的其它配置文件片段

Syntax: include file | mask; 

    Default:— 

    Context:any

四、load_module file; # 指明要裝載的動態模塊

Syntax: load_module file; 

    Default:— 

    Context:main

性能優化相關的配置:

一、worker_processes number | auto; # worker進程的數量;一般應該爲當前主機的cpu的物理核心數

Syntax: worker_processes number | auto; 

    Default:worker_processes 1; 

    Context:main

clipboard.png

若是隻有兩個進程

clipboard.png

[root@localhost /etc/nginx]#nginx -t
[root@localhost /etc/nginx]#nginx -s reload

![圖片上傳中...]

[root@localhost /etc/nginx]#nginx -t
[root@localhost /etc/nginx]#nginx -s reload

二、worker_cpu_affinity cpumask …; # 定義worker進程和cpu的綁定

worker_cpu_affinity auto [cpumask]; 

    Default:— 

    Context:main                         

    CPU MASK: 

        00000001:0號CPU 

        00000010:1號CPU 

        00000100: 2號CPU 

        … …

綁定cpu,默認次序0、一、二、3

[root@localhost /etc/nginx]#nginx -t
[root@localhost /etc/nginx]#nginx -s reload

反向綁定cpu,三、二、一、0

[root@localhost /etc/nginx]#nginx -t
[root@localhost /etc/nginx]#nginx -s reload

三、worker_priority number; # 指定worker進程的nice值,設定worker進程優先級;[-20,20]

Syntax: worker_priority number; 

    Default:worker_priority 0; 

    Context:main

默認優先級

[root@localhost /etc/nginx]#ps axo comm,pid,psr,ni | grep nginx
nginx 4795 2 0
nginx 43059 3 0 優先級爲0
nginx 43060 2 0 優先級爲0設定優先級

[root@localhost /etc/nginx]#nginx -t
[root@localhost /etc/nginx]#nginx -s reload
[root@localhost /etc/nginx]#ps axo comm,pid,psr,ni | grep nginx
nginx 4795 2 0
nginx 43361 3 -5 優先級爲-5
nginx 43362 2 -5 優先級爲-5四、worker_rlimit_nofile number; # worker進程所可以打開的文件數量上限

Syntax: worker_rlimit_nofile number; 

    Default:— 

    Context:main

[root@localhost /etc/nginx]#vim nginx.conf

調試、定位問題:

一、daemon on|off; # 是否以守護進程方式運行Nignx

Syntax: daemon on | off; 

    Default:daemon on; 

    Context:main

二、master_process on|off; # 是否以master/worker模型運行nginx;默認爲on

Syntax: master_process on | off; 

    Default:master_process on; 

    Context:main

三、error_log file [level]; # 定義錯誤日誌文件路徑與級別

Syntax: error_log file [level]; 

    Default:error_log logs/error.log error; 

    Context:main, http, mail, stream, server, location

事件驅動相關的配置:

events { 

    … 

}

一、worker_connections number; # 每一個worker進程所可以打開的最大併發鏈接數數量

Syntax: worker_connections number; 

    Default:worker_connections 512; 

    Context:events 

    worker_processes * worker_connections得出最大併發鏈接數

二、use method; # 指明併發鏈接請求的處理方法

Syntax: use method; 

    Default:— 

    Context:events 

        use epoll;

三、accept_mutex on | off; # 處理新的鏈接請求的方法;on意味着由各worker輪流處理新請求,Off意味着每一個新請求的到達都會通知全部的worker進程;建議使用on

Syntax: accept_mutex on | off; 

    Default:accept_mutex off; 

    Context:events

主配置文件結構:

main block:主配置段,也即全局配置段;

event {

}:事件驅動相關的配置;

http {

}:http/https 協議相關的配置段;

mail {

}

stream {

}

http協議的相關配置:

http {

...
...:各server的公共配置
server {
    ...
}:每一個server用於定義一個虛擬主機;
server {
    ...
    listen 
    server_name
    root
    alias
    location [OPERATOR] URL {
        ...
        if CONDITION {
            ...
        }
    }
}

}

相關文章
相關標籤/搜索