文章原創於公衆號:程序猿周先森。本平臺不定時更新,喜歡個人文章,歡迎關注個人微信公衆號。
nginx
以前其實寫過一篇文章具體介紹過:最基礎的Nginx教學,當時有提到過Nginx有一個重要的功能:負載均衡。因此這篇文章主要講講Nginx如何實現反向代理以及在Nginx中負載均衡的參數使用。算法
1、代理segmentfault
正向代理後端
正向代理也是你們最常接觸的到的代理模式,那究竟什麼是正向代理呢?咱們都知道Google在國內是沒法正常訪問的,可是某些時候咱們因爲技術問題須要去訪問Google時,咱們會先找到一個能夠訪問Google的代理服務器,咱們將請求發送到代理服務器,代理服務器去訪問Google,而後將訪問到的數據返回給咱們,這樣的過程就是正向代理。緩存
正向代理的特色安全
正向代理最大的特色是客戶端須要明確知道要訪問的服務器地址,Google服務器只清楚請求來自哪一個代理服務器,而不清楚來自哪一個具體的客戶端,正向代理能夠隱藏真實客戶端的具體信息。服務器
客戶端必須設置正向代理服務器,並且須要知道正向代理服務器的IP地址以及代理程序的端口。一句話來歸納就是正向代理代理的是客戶端,是一個位於客戶端和Google服務器之間的服務器,爲了從Google服務器取得數據,客戶端向代理服務器發送一個請求並指定目標(Google服務器),而後代理向原始服務器轉交請求並將得到的數據返回給客戶端。微信
正向代理的使用:網絡
反向代理多線程
說完了什麼是正向代理,咱們接下來看看什麼叫作反向代理,若是咱們網站每日訪問量達到某個上限,單個服務器遠遠不能符合咱們平常需求,這時候咱們首先會想到分佈式部署。經過部署多臺服務器來解決訪問人數限制的問題,而後咱們功能其實大部分都是經過Nginx反向代理來實現的。咱們能夠看下圖:
反向代理的特色
咱們能夠清楚的看到,多個客戶端給服務器發送的請求,Nginx服務器接收到請求之後,按照必定的規則轉發到不一樣的服務器進行業務邏輯處理。此時請求來源於哪一個客戶端是肯定的,可是請求由哪臺服務器處理的並不明確,Nginx扮演的就是一個反向代理角色。能夠這樣來理解,反向代理對外都是透明的,訪問者並不知道本身訪問的是一個代理。反向代理代理的是服務端,主要用於服務器集羣分佈式部署的狀況下,反向代理隱藏了服務器的信息。
反向代理的使用:
正向代理與反向代理區別
服務端中咱們最常使用的反向代理的工具就是Nginx。
2、基本架構
Nginx在啓動後以daemon的方式在後臺運行,會有一個master進程和多個worker進程:
master進程:主要用來管理worker進程,包含:
worker進程:處理基本的網絡事件了。多個worker進程之間是對等的,他們同等競爭來自客戶端的請求,各進程互相之間是獨立的。一個請求只能在一個worker進程中處理,一個worker進程,不可能處理其它進程的請求。worker進程的個數是能夠設置的,通常咱們會設置與機器cpu核數一致,或者直接設置參數worker_processes auto;
Nginx基本架構以下:
咱們能夠輸入nginx -s reload來重啓Nginx,nginx -s stop來中止Nginx的運行,執行這些命令時其實會啓動一個新的Nginx進程,而新的Nginx進程在解析到reload參數後,其實就能夠知道用戶執行這個命令是控制Nginx從新加載配置文件,因而向master進程發送信號。master進程接到信號會先從新加載配置文件,而後啓動新的worker進程並向全部舊worker進程發送信號提示老進程能夠中止運行了。新的worker啓動成功後就開始接收新的請求,而舊worker在收到來自master的信號後中止接收新的請求,在未處理完的請求處理完成後進程就會退出。因此說使用nginx -s reload命令重啓Nginx的時候服務是不中斷的。
3、Nginx處理客戶端請求方式
剛纔有講到過每一個worker進程都是從master進程分支的,因此在master進程裏面須要先創建好須要監聽的socket而後再分支出多個worker進程。全部worker進程listenfd事件會在新鏈接時變成可讀,爲保證只有一個進程處理該鏈接,因此須要設置互斥鎖,全部worker進程須要搶互斥鎖,搶到互斥鎖的work進程註冊listenfd讀事件,在listenfd讀事件裏調用accept接受該鏈接。當Nginx監聽80端口時,一個客戶端的鏈接請求過來的時候,每一個worker進程都會去搶互斥鎖註冊listenfd讀事件。當一個worker進程在accept這個鏈接以後,就開始處理請求獲取數據,再將數據返回給客戶端,而後斷開鏈接,到這裏一個請求結束。
一個請求,徹底由worker進程來處理,並且只在一個worker進程中處理。
我下面貼一個簡單的配置:
server {
listen 80;server_name aaa.com www.aaa.com;}
server {
listen 80;server_name aaa.cn www.aaa.cn;}
server {
listen 80;server_name aaa.org www.aaa.org;}
當接收到客戶端http請求,Nginx根據請求頭的Host字段決定請求應該由哪一臺服務器處理,若是Host字段的值沒有匹配的服務器或者請求中沒有Host字段,Nginx會將請求路由至這個端口的默認服務器。沒有顯示配置默認服務器,則默認服務器則爲第一個配置。固然咱們還可使用default_server參數指定默認服務器。
server {
listen 80 default_server; server_name aaa.com www.aaa.com;
}
這裏須要注意一下:配置默認服務器是監聽端口號,而不是服務器名稱。
4、Nginx實現高併發
Nginx內部採用了異步非阻塞的方式處理請求,使用了epoll和大量的底層代碼優化。能夠同時處理成千上萬個請求的。
異步非阻塞:每進來一個request,會有一個worker進程去處理。但不是全程的處理,處理到什麼程度呢?處理到可能發生阻塞的地方,好比向後端服務器轉發request,並等待請求返回。這個處理的worke會在發送完請求後註冊一個事件:「若是upstream返回了,再進行執行接下來的工做」。此時,若是再有request 進來,他就能夠很快再按這種方式處理。而一旦後端服務器返回了,就會觸發這個事件,worker進程會來接手request接着往下執行。
而Nginx採用一個master進程,多個woker進程的模式。master進程主要負責收集、分發請求。每當一個請求過來時,master就拉起一個worker進程負責處理這個請求。同時master進程也負責監控woker的狀態,保證高可靠性,woker進程通常設置爲跟cpu核心數一致。Nginx的woker進程在同一時間能夠處理的請求數只受內存限制,能夠處理多個請求。Nginx 的異步非阻塞工做方式能夠把當中的進程空閒等待時間利用起來,所以表現爲少數幾個進程就解決了大量的併發問題。
Nginx中以epoll爲例子,當事件沒準備好時,放到epoll裏面,事件準備好了,Nginx就去讀寫,當讀寫返回EAGAIN時,就將它再次加入到epoll裏面。這樣,只要有事件準備好了,Nginx就能夠去處理它,只有當全部事件都沒準備好時,纔在epoll裏面等着。這樣便實現了所謂的併發處理請求,可是線程只有一個,因此同時能處理的請求固然只有一個了,只是在請求間進行不斷地切換而已。
Nginx單線程機制與多線程相比優點:
5、Nginx負載均衡的算法及參數
上面是最基本的4種算法,咱們還能夠經過改變參數來自行配置負載均衡:
upstream localhost{
ip_hash;
server 127.0.0.1:9090 down;
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:6060;
server 127.0.0.1:7070 backup;
}
歡迎關注個人我的公衆號:程序猿周先森