什麼是**伺服器?
定義:**(英語:proxy),也稱網路**,是一種特殊的網路服務,允許乙個網路終端(一般為客戶端)
通過這個服務與另乙個網路終端(一般為伺服器)進行非直接的連線。一些閘道器、路由器等網路裝置具備網路**功能。一般認為**服務有利於保障網路終端的隱私或安全,防止攻擊。
提供**服務的電腦系統或其它型別的網路終端稱為**伺服器(一般作用在客戶端)(英文:proxy server)。
乙個完整的**請求過程為:客戶端首先與**伺服器建立連線,接著根據**伺服器所使用的**協議,請求對目標伺服器建立連線、或者獲得目標伺服器的指定資源(如:檔案)。
**伺服器**方式有很多(http**,vpn**,反向**等等),我們這裡主要學習反向**。
什麼是正向**伺服器 ?
是乙個位於客戶端和原始伺服器(origin server)之間的伺服器,為了從原始伺服器取得內容,客戶端向**傳送乙個請求並指定目標(原始伺服器),然後**向原始伺服器轉交請求並將獲得的內容返回給客戶端。客戶端必須要進行一些特別的設定才能使用正向**。
什麼是反向**伺服器?
瀏覽器傳送請求,在**伺服器端接收客戶的請求,然後把請求分發給具體的web伺服器進行處理,然後在將伺服器的響應返回給客戶。(反向**伺服器一般作用在伺服器端)
nginx是什麼?
為什麼要用nginx?
這要歸功於它一系列的優點:
跨平台、配置簡單
非阻塞、高併發連線:處理2-3萬併發連線數,官方監測能支援5萬併發
記憶體消耗小:開啟10個nginx才佔150m記憶體
成本低廉:開源
內建的健康檢查功能:如果有乙個伺服器宕機,會做乙個健康檢查,再傳送的請求就不會傳送到宕機的伺服器了。重新將請求提交到其他的節點上。
節省寬頻:支援gzip壓縮,可以新增瀏覽器本地快取
穩定性高:宕機的概率非常小
master/worker結構:乙個master程序,生成乙個或者多個worker程序。
接收使用者請求是非同步的:瀏覽器將請求傳送到nginx伺服器,它先將使用者請求全部接收下來,再一次性傳送給後端web伺服器,極大減輕了web伺服器的壓力
邊接收web伺服器的返回報文,邊傳送給瀏覽器
網路依賴性比較低,只要ping通就可以負載均衡
可以有多台nginx伺服器
事件驅動:通訊機制採用epoll模型
為什麼nginx效能這麼高?
得益於它的事件處理機制:
非同步非阻塞事件處理機制:運用了epoll模型,提供了乙個佇列,排隊解決;
為什麼不使用多執行緒?
因為執行緒建立和上下文的切換非常消耗資源,執行緒占用記憶體大,上下文切換占用cpu也很高,採用epoll模型避免了這個缺點。
執行緒和執行緒池的理解
nginx的程序模型是什麼樣的呢?
nginx是以多程序的方式來工作的,當然nginx也是支援多執行緒的方式的,只是我們主流的方式還是多程序的方式,也是nginx的預設方式。nginx採用多程序的方式有諸多好處 .
(1) nginx在啟動後,會有乙個master程序和多個worker程序。master程序主要用來管理worker程序,包含:接收來自外界的訊號,向各worker程序傳送訊號,監控 worker程序的執行狀態,當worker程序退出後(異常情況下),會自動重新啟動新的worker程序。而基本的網路事件,則是放在worker程序中來處理了 。多個worker程序之間是對等的,他們同等競爭來自客戶端的請求,各程序互相之間是獨立的 。乙個請求,只可能在乙個worker程序中處理,乙個worker程序,不可能處理其它程序的請求。 worker程序的個數是可以設定的,一般我們會設定與機器cpu核數一致,這裡面的原因與nginx的程序模型以及事件處理模型是分不開的 。
(3) worker程序又是如何處理請求的呢?我們前面有提到,worker程序之間是平等的,每個程序,處理請求的機會也是一樣的。當我們提供80埠的http服務時,乙個連線請求過來,每個程序都有可能處理這個連線,怎麼做到的呢?首先,每個worker程序都是從master程序fork過來,在master程序裡面,先建立好需要listen的socket之後,然後再fork出多個worker程序,這樣每個worker程序都可以去accept這個socket(當然不是同乙個socket,只是每個程序的這個socket會監控在同乙個ip位址與埠,這個在網路協議裡面是允許的)。一般來說,當乙個連線進來後,所有在accept在這個socket上面的程序,都會收到通知,而只有乙個程序可以accept這個連線,其它的則accept失敗,這是所謂的驚群現象。當然,nginx也不會視而不見,所以nginx提供了乙個accept_mutex這個東西,從名字上,我們可以看這是乙個加在accept上的一把共享鎖。有了這把鎖之後,同一時刻,就只會有乙個程序在accpet連線,這樣就不會有驚群問題了。accept_mutex是乙個可控選項,我們可以顯示地關掉,預設是開啟的。當乙個worker程序在accept這個連線之後,就開始讀取請求,解析請求,處理請求,產生資料後,再返回給客戶端,最後才斷開連線,這樣乙個完整的請求就是這樣的了。我們可以看到,乙個請求,完全由worker程序來處理,而且只在乙個worker程序中處理。
(4):,nginx採用這種程序模型有什麼好處呢?採用獨立的程序,可以讓互相之間不會影響,乙個程序退出後,其它程序還在工作,服務不會中斷,master程序則很快重新啟動新的worker程序。當然,worker程序的異常退出,肯定是程式有bug了,異常退出,會導致當前worker上的所有請求失敗,不過不會影響到所有請求,所以降低了風險。當然,好處還有很多,大家可以慢慢體會。
(5).有人可能要問了,nginx採用多worker的方式來處理請求,每個worker裡面只有乙個主線程,那能夠處理的併發數很有限啊,多少個worker就能處理多少個併發,何來高併發呢?非也,這就是nginx的高明之處,nginx採用了非同步非阻塞(詳見非同步非阻塞理解)的方式來處理請求,也就是說,nginx是可以同時處理成千上萬個請求的 .對於iis伺服器每個請求會獨佔乙個工作執行緒,當併發數上到幾千時,就同時有幾千的執行緒在處理請求了。這對作業系統來說,是個不小的挑戰,執行緒帶來的記憶體占用非常大,執行緒的上下文切換帶來的cpu開銷很大,自然效能就上不去了,而這些開銷完全是沒有意義的。我們之前說過,推薦設定worker的個數為cpu的核數,在這裡就很容易理解了,更多的worker數,只會導致程序來競爭cpu資源了,從而帶來不必要的上下文切換。而且,nginx為了更好的利用多核特性,提供了cpu親緣性的繫結選項,我們可以將某乙個程序繫結在某乙個核上,這樣就不會因為程序的切換帶來cache的失效
nginx是如何處理乙個請求的呢?
首先,nginx在啟動時,會解析配置檔案,得到需要監聽的埠與ip位址,然後在nginx的master程序裡面,先初始化好這個監控的socket(建立socket,設定addrreuse等選項,繫結到指定的ip位址埠,再listen),然後再fork(乙個現有程序可以呼叫fork函式建立乙個新程序。由fork建立的新程序被稱為子程序 )出多個子程序出來,然後子程序會競爭accept新的連線。此時,客戶端就可以向nginx發起連線了。當客戶端與nginx進行三次握手,與nginx建立好乙個連線後,此時,某乙個子程序會accept成功,得到這個建立好的連線的socket,然後建立nginx對連線的封裝,即ngx_connection_t結構體。接著,設定讀寫事件處理函式並新增讀寫事件來與客戶端進行資料的交換。最後,nginx或客戶端來主動關掉連線,到此,乙個連線就壽終正寢了。
l 當然,nginx也是可以作為客戶端來請求其它server的資料的(如upstream模組),此時,與其它server建立的連線,也封裝在ngx_connection_t中。作為客戶端,nginx先獲取乙個ngx_connection_t結構體,然後建立socket,並設定socket的屬性( 比如非阻塞)。然後再通過新增讀寫事件,呼叫connect/read/write來呼叫連線,最後關掉連線,並釋放ngx_connection_t。
下圖是nginx的應用場景:
nginx的負載均衡功能請查閱:
quartz個人簡單理解
乙個簡單的任務類實現job介面 該類只包含了要執行的任務內容,不包含該任務的name或者屬於哪個組,也不包含如何去執行任務,比如什麼時候開始,執行幾次,執行間隔。jobdetail實現了job例項類的自生資訊,比如name,所屬的組,quartz每次執行任務都會新建乙個job例項,而不是一直使用同乙...
介面的個人理解,簡單易懂
1,內部介面,在乙個類中定義乙個介面,那麼這個類就可以通過這個介面去操作外部類的屬性了和方法了。內部介面的精髓 1 通過繼承該類中的介面,並且傳入繼承介面的物件,可以實現安對該類屬性的修改 2 並且進行實現,可以對物件的屬性直接進行修改 預留介面是等著實現的類被呼叫,注意這裡的被呼叫關係 2,繼承的...
Shiro簡單入門 個人理解 2
今天開始了shiro認證及授權的部分,認證及授權是shiro的主要功能,雖然shiro還具有加密等功能,但在實際開發時,很少會使用到,在公司一般都有自己的一套加密方式,具體我就不說話了,畢竟有保密協議 廢話不多說開始吧 首先開始shiro認證流程 身份認證 判定使用者是否是系統的合法使用者。使用者訪...