【前言】部署服務器用到了nginx,相比較於apache併發能力更強,優勢也比其多得多。雖然個人項目可能用不到這麼多性能,仍是部署一個流行的服務器吧!html
此篇博文主要學習nginx(ingine x)的反向代理、負載均衡原理,並介紹一下分佈式下sesssion保持。(分佈式和集羣的區別?下面有)java
正向代理,也就是傳說中的代理,他的工做原理就像一個跳板,簡單的說,我是一個用戶,我訪問不了某網站,可是我能訪問一個代理服務器。這個代理服務器呢,他能訪問那個我不能訪問的網站因而我先連上代理服務器,告訴他我須要那個沒法訪問網站的內容,代理服務器去取回來,而後返回給我。從網站的角度,只在代理服務器來取內容的時候有一次記錄,有時候並不知道是用戶的請求,也隱藏了用戶的資料,這取決於代理告不告訴網站。linux
結論就是 正向代理 是一個位於客戶端和原始服務器(origin server)之間的服務器,爲了從原始服務器取得內容,客戶端向代理髮送一個請求並指定目標(原始服務器),而後代理向原始服務器轉交請求並將得到的內容返回給客戶端。客戶端必需要進行一些特別的設置才能使用正向代理。nginx
繼續舉例:web
例用戶訪問 http://ooxx.me/readme,但ooxx.me上並不存在readme頁面,他是偷偷從另一臺服務器上取回來,而後做爲本身的內容吐給用戶,但用戶並不知情。這很正常,用戶通常都很笨。這裏所提到的 ooxx.me 這個域名對應的服務器就設置了反向代理功能。redis
結論就是 反向代理正好相反,對於客戶端而言它就像是原始服務器,而且客戶端不須要進行任何特別的設置。客戶端向反向代理 的命名空間(name-space)中的內容發送普通請求,接着反向代理將判斷向何處(原始服務器)轉交請求,並將得到的內容返回給客戶端,就像這些內容 本來就是它本身的同樣。算法
從用途 上來說:數據庫
正向代理的典型用途是爲在防火牆內的局域網客戶端提供訪問Internet的途徑;正向代理還可使用緩衝特性減小網絡使用率。apache
反向代理的典型用途是將 防火牆後面的服務器提供給Internet用戶訪問;反向代理還能夠爲後端的多臺服務器提供負載平衡,或爲後端較慢的服務器提供緩衝服務。後端
另外,反向代理還能夠啓用高級URL策略和管理技術,從而使處於不一樣web服務器系統的web頁面同時存在於同一個URL空間下。
從安全性 來說:
正向代理容許客戶端經過它訪問任意網站而且隱藏客戶端自身,所以你必須採起安全措施以確保僅爲通過受權的客戶端提供服務;
反向代理對外都是透明的,訪問者並不知道本身訪問的是一個代理。
Nginx服務器就是反向代理服務器,只作請求的轉發,後臺有多個http服務器提供服務,nginx的功能就是把請求轉發給後面的服務器,並把結果返回給客戶端。實如今同一個域名之下,有多臺服務器,並實現服務器負載均衡。
負載均衡,英文名稱爲Load Balance,其意思就是算力分攤到多個操做單元上進行執行,例如Web服務器、FTP服務器、企業關鍵應用服務器和其它關鍵任務服務器等,從而共同完成工做任務。
負載均衡創建在現有網絡結構之上,它提供了一種廉價有效透明的方法擴展網絡設備和服務器的帶寬、增長吞吐量、增強網絡數據處理能力、提升網絡的靈活性和可用性。負載均衡,核心就是網絡流量分發,分不少維度。從網絡層看,基本是四層(TCP,UDP),和七層(HTTP,HTTPS等),基本就是解析到對應的網絡層,而後根據不一樣特徵分發。好比四層的,基本就是根據鏈接信息(TCP)或者自己的特徵(源IP,目標IP)等作。七層的,就能夠用域名(HTTP頭裏的Host),URL,Cookie,Header這些來作。
(1)從實現上看,基本能夠分軟負載均衡和反向代理:
(2)從實現方式看,有軟件負載均衡和硬件負載均衡:
每一個雲服務都會提供負載均衡服務(負載均衡服務_流量分發服務-網易雲),拿來直接用就好啦,省時又省力,能夠將更多精力放在覈心業務上面。
nginx做爲負載均衡服務器,用戶請求先到達nginx,再由nginx根據負載配置將請求轉發至tomcat服務器。
nginx負載均衡服務器:192.168.3.43
tomcat1服務器:192.168.3.43:8080
tomcat2服務器:192.168.3.43:8081
upstream tomcatserver1 { server 192.168.3.43:8080 weight=2; server 192.168.3.43:8082 weight=1; #多加了此臺服務器,並增長了負載的權重。性能高的服務器作的事情多 } upstream tomcatserver2 { server 192.168.3.43:8082; } #第一臺服務器 server { listen 80; server_name 8080.zcinfo.com; location / { proxy_pass http://tomcatserver1; index index.html index.htm; } } #第二臺服務器 server { listen 80; server_name 8082.zcinfo.com; location / { proxy_pass http://tomcatserver2; index index.html index.htm; } }
這樣的狀況下,就反向代理成功了。會出現兩個端口下的頁面輪詢。那麼負載均衡體如今哪裏呢?
上面的weight大小就是一種負載均衡的策略,weight=2的會連續出現兩次,1的出現一次。總的來講,nginx提供五種負載均衡的策略。
(1)輪詢(默認)
每一個請求按時間順序逐一分配到不一樣的後端服務器,若是後端服務器down掉,能自動剔除。
upstream backserver {
server 192.168.0.14;
server 192.168.0.15;
}
(2)指定權重
指定輪詢概率,weight和訪問比率成正比,用於後端服務器性能不均的狀況。 默認爲1
upstream backserver {
server 192.168.0.14 weight=3;
server 192.168.0.15 weight=10;
}
(3)IP綁定 ip_hash
每一個請求按訪問ip的hash結果分配,這樣每一個訪客固定訪問一個後端服務器,能夠解決session的問題。由於對於集羣問題很差解決session問題。
upstream backserver {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}
(4)fair(第三方)
按後端服務器的響應時間來分配請求,響應時間短的優先分配。
upstream backserver {
server server1;
server server2;
fair;
}
(5)url_hash(第三方)
按訪問url的hash結果來分配請求,使每一個url定向到同一個後端服務器,後端服務器爲緩存時比較有效。
upstream backserver {
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
}
proxy_pass http://backserver/;
upstream backserver{
ip_hash;
server 127.0.0.1:9090 down; #(down 表示單前的server暫時不參與負載)
server 127.0.0.1:8080 weight=2; # (weight 默認爲1.weight越大,負載的權重就越大)
server 127.0.0.1:6060;
server 127.0.0.1:7070 backup; # (其它全部的非backup機器down或者忙的時候,請求backup機器)
}
max_fails :容許請求失敗的次數默認爲1.當超過最大次數時,返回proxy_next_upstream 模塊定義的錯誤
fail_timeout:max_fails次失敗後,暫停的時間
負載均衡的應用背景下是多臺服務器,那麼對於多臺服務器這樣進行session保持呢?
我有一篇文章已經介紹了session,此處再也不贅述。下面介紹一下session的管理,例如在java服務器下,例如tomcat服務器sessionid會以jsessionid的名稱存在cookie中,以cookie的形式和服務器通訊。
不一樣的服務器、不一樣的語言框架都有不一樣的實現。好比java的服務器,有的是用文件方式來存儲的;有的是用內存cache的方式來存儲的;有的語言的服務器將數據作加密,而後設置成cookie,存到了客戶端(瀏覽器)。那這些實現方式都有哪些優缺點呢?咱們逐個來分析。
文件方式:這種方式,將文件做爲一個map,當新增一個數據的時候,就在文件中增長相似這樣的一條數據:
angOwberup =>
data={"user":{"id":1,"nickname":"老王"}};
expiry="2016-10-0100:00:00"
(固然,具體實現的時候有多是用的二進制方式,而不是字符串)
這種方式的好處,就是可以存儲大量的用戶session,使得這個session有效期能夠比較長(好比:三個月用戶不用登陸)。不過這個方式也有對應的問題,就是文件操做比較麻煩。好比,有一個用戶的session過時了,須要刪掉這條記錄,那這個文件就須要挪動或重寫。
cache方式:有好多web端的邏輯服務器都採用這種方式。這種方式好處很是明顯,就是實現起來很是簡單。將全部數據放入到內存cache中。若是有失效,直接內存刪除就能夠了。不過帶來的問題也很明顯,當服務器重啓之後,全部session都丟失了。或者當有大量用戶登陸(也有多是遭受攻擊),就會很快讓cache被充滿,而後大量session被LRU算法淘汰,形成session的大量失效,使得用戶須要反覆登陸等操做。
除了上述說到的優缺點之外,第一和第二,He兩種方式還有另一個問題,就是當我有不止一臺服務器的時候,不一樣服務器間的session數據共享就成問題了。好比,最初我只有一臺服務器1,他的session裏記錄了user-1和user-2的數據。這個時候,我須要增長一臺服務器2。當nginx把用戶的請求轉發到服務器2的時候,他就傻眼了:用戶帶了一個jsession_id=angOwberup這個的cookie過來,而在他的session管理器裏卻找不到這樣一個session數據。那該怎麼辦?!
所以,就出現了咱們文章一開始提到的問題:在分佈式系統裏,用戶session如何才能實現同步?
(PS:分佈式和集羣的區別在於分佈式解決的是壓力集中問題,每一個單元任務都不同;集羣是解決大項目臃腫問題,是同一個項目分散在不一樣單元上。因此此處用分佈式比較合適)
有了上面的狀況,咱們就必需要去考慮,如何在多個服務器之間實現session同步這個操做。常見的作法有如下幾種,咱們逐個來看看: