什麼是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上的epoll,epoll是大併網絡鏈接的利器 複製代碼
爲何是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 內存資源,及時沒有做任何有意義的事
- 把一個進程或線程做爲事件消費者,當一個請求產生事件被該進程處理時,直到請求處理結束時進程資源都將被這一個請求佔用
- Apache採用的所謂事件驅動僅僅是體如今TCP鏈接的創建和關閉事件上
- nginx服務器
- 不會使用進程或者線程做爲事件消費者,所謂的事件消費者只能是某個模塊(在這裏沒有進程的概念)
- 只有事件收集和分發器纔有資格佔用進程資源
- 重要差異
- 前者是每一個事件消費者獨佔一個進程資源,後者的事件消費者只是被事件分發者進程短時間調用而已
- nginx這種設計的一個弊端
- 即每一個事件消費者都不能有阻塞行爲,不然會長時間佔用事件分發者進程而致使其它事件得不到及時響應,尤爲是每一個消費者不可讓進程轉爲休眠或等待狀態,這都增長了碼畜們的開發難度
手摸手教你使用nginx
準備工做
安裝nginx開發所需的最基本的庫 如下是完成web服務器功能所須要的基本包安全
- 使用uname -a 查看linuxe內核是否時2.6及以上版本
由於只有linux2.6及以上版本才支持epoll,可以更大限度發揮nginx的威力服務器
- GCC編譯器 使用yum install -y gcc安裝
GCC(GNU Compile Collection)能夠用來編譯C語言程序,由於有時候nginx不會直接提供二進制可執行程序,須要本身編譯
- PCRE庫
Perl正則兼容表達式包,pcre-devel時PCRE作二次開發時所須要的開發庫,也是nginx開發所必需的
- zlib庫 yum install -y gzip gzip-devel
nginx.conf中配置了gzip on對Http 包的內容做gzip格式壓縮,須要用 zlip-devel是二次開發所須要的庫
- OpenSSL庫 yum install -y openssl openssl-devel
若是想使用更安全的SSL 協議傳輸HTTP,就須要該包,若是要使用MD5或者SHA1包,也須要Openssl包
須要瞭解的幾個目錄
- nginx源碼存放目錄,隨便放,沒人管你,看我的癖好
- Nginx編譯階段產生的中間目錄
該目錄用於存放configure和make命令執行後,生成的中間目錄,默認狀況下,生產objs目錄存放在源碼目錄中
複製代碼
- 部署目錄默認 /usr/local/nginx
存放nginx運行期間所需的二進制文件,配置文件等。 複製代碼
- 日誌文件存放目錄
若是你要研究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只提供純管理工做,只提供命令行服務。
2多worker進程能夠提升服務的健壯型,能夠充分利用多核cpu
複製代碼
爲何須要把nginx的worker 進程數量設置的根cpu核心數一致呢
- 在apache上每一個進程每一時刻只能處理一個請求,所以要想併發處理更多的併發請求數就要設置不少個進程,而大量的進程間切換很消耗內存資源
- 而nginx的一個worker進程處理的請求數只受限於內存大小,而且worker進程之間處理併發請求時幾乎沒有同步鎖的限制,worker進程也不會進入睡眠狀態,所以當nginx進程與cpu核數一致時(最好每個worker綁定一個內核),進程切換的代價是最小的
- 將進程與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
- user username [groupname];
-
事件類配置
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> } 複製代碼} "http中還有賊多的配置 好比tcp網絡連接 內存資源管理 對客戶端請求的限制 文件操做的優化等等,等用到了能夠具體研究" 複製代碼<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> } 複製代碼
}
反向代理服務器配置
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_log的log_format日誌格式配置中使用???
複製代碼
}
反向代理配置在location模塊中,配置以下
upstream backen {
.....
}
複製代碼server{ location /{ proxy_pass http://backend; proxy_set_header Host $host #默認狀況反向代理是不會轉發請求中的host頭部,若是須要轉發,使用proxy_set_header配置 } } 複製代碼