nginx 負載平衡session複製解決方案

來源:互聯網
上載者:User

nginx 負載平衡,必定要用到分布式叢集方案,只要涉及分布式,session共用必定是一個大問題,不僅僅是nginx的問題。我們用nginx做負載平衡,同一個請求不一定會被分配到哪個伺服器中,那麼我們下一個請求可能又被分到了其他的伺服器,這種情境下,就會造成session丟失問題,要出大問題了。這種情況在登陸問題中比較常見,例如:我們第一個請求(由A伺服器響應)可以進入到登陸介面,此時A產生的驗證碼存在於A 的 session中,那麼我們輸完登陸資訊和驗證碼之後提交,此次請求被分到B伺服器來處理,這樣B肯定擷取不到A中session的資訊,拿不到對應的驗證碼,當然出現的錯誤就是驗證碼不正確了。那麼怎樣解決分布式中session複製(共用)問題呢。從網上差了些資料,整理如下: 1.不使用session,換用cookie

session是存放在伺服器端的,cookie是存放在用戶端的,我們可以把使用者訪問頁面產生的session放到cookie裡面,就是以cookie為中轉站。你訪問web伺服器A,產生了session然後把它放到cookie裡面,當你的請求被分配到B伺服器時,伺服器B先判斷伺服器有沒有這個session,如果沒有,再去看看用戶端的cookie裡面有沒有這個session,如果也沒有,說明session真的不存,如果cookie裡面有,就把cookie裡面的sessoin同步到伺服器B,這樣就可以實現session的同步了。

說明:這種方法實現起來簡單,方便,也不會加大資料庫的負擔,但是如果用戶端把cookie禁掉了的話,那麼session就無從同步了,這樣會給網站帶來損失;cookie的安全性不高,雖然它已經加了密,但是還是可以偽造的。 2.session存在memcache或者redis中

memcache可以做分布式,php設定檔中設定儲存方式為memcache,這樣php自己會建立一個session叢集,將session資料存放區在memcache中。

說明:以這種方式來同步session,不會加大資料庫的負擔,並且安全性比用cookie大大的提高,把session放到記憶體裡面,比從檔案中讀取要快很多。但是memcache把記憶體分成很多種規格的儲存塊,有塊就有大小,這種方式也就決定了,memcache不能完全利用記憶體,會產生記憶體片段,如果儲存塊不足,還會產生記憶體溢出。

redis通常用於項目的緩衝,我們可以將session緩衝到redis中,達到session複製的目的。目前此種方案是 nginx + redis + tomcat 實現的,如下:
(1)將所需jar包加入到tomcat的lib目錄下(tomcat-redis-session-manager相應的jar包,主要有三個)。
(2)配置tomcat目錄下的conf/context.xml,加入以下內容:

<Valve className="com.radiadesign.catalina.session.RedisSessionHandlerValve" />        <Manager className="com.radiadesign.catalina.session.RedisSessionManager"                host="192.168.0.222"   #redis地址                port="6379"                #redis連接埠                database="0"                maxInactiveInterval="60"/> #session失效時間
3. 將session存在資料庫中

用資料庫來同步session,會加大資料庫的IO,增加資料庫的負擔。而且資料庫讀寫速度較慢,不利於session的適時同步,不推薦。 4.nginx ip_hash 策略

Nginx負載平衡的策略:
nginx 的 upstream目前支援 4 種方式的分配
1)、輪詢(預設)
每個請求按時間順序逐一分配到不同的後端伺服器,如果後端伺服器down掉,能自動剔除。
2)、weight
指定輪詢幾率,weight和訪問比率成正比,用於後端伺服器效能不均的情況。
3)、ip_hash
每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個後端伺服器,可以解決session的問題。
4)、fair(第三方)
按後端伺服器的回應時間來分配請求,回應時間短的優先分配。
5)、url_hash(第三方)

nginx中的ip_hash技術能夠將某個ip的請求定向到同一台後端,這樣一來這個ip下的某個用戶端和某個後端就能建立起穩固的session,ip_hash是在upstream配置中定義的:

    upstream nginx.example.com          {                ip_hash;                   server 192.168.1.111:80;                    server 192.168.1.114:80;          }          server          {                   listen 80;                   location /                   {                           proxy_pass                          http://nginx.example.com;                   }       }  

ip_hash是容易理解的,但是因為僅僅能用ip這個因子來分配後端,因此ip_hash是有缺陷的,不能在一些情況下使用:

(1) nginx不是最前端的伺服器。
ip_hash要求nginx一定是最前端的伺服器,否則nginx得不到正確ip,就不能根據ip作hash。譬如使用的是squid為最前端,那麼nginx取ip時只能得到squid的伺服器ip地址,用這個地址來作分流是肯定錯亂的。

(2) nginx的後端還有其它方式的負載平衡。
假如nginx後端又有其它負載平衡,將請求又通過另外的方式分流了,那麼某個用戶端的請求肯定不能定位到同一台session應用伺服器上。這麼算起來,nginx後端只能直接指嚮應用伺服器,或者再搭一個squid,然後指嚮應用伺服器。最好的辦法是用 location作一次分流,將需要session的部分請求通過ip_hash分流,剩下的走其它後端去。 5.upstream_hash

為瞭解決ip_hash的一些問題,可以使用upstream_hash這個第三方模組,這個模組多數情況下是用作url_hash的,但是並不妨礙將它用來做session共用:
假如前端是squid,他會將ip加入x_forwarded_for這個http_header裡,用upstream_hash可以用這個頭做因子,將請求定向到指定的後端:
可見這篇文檔:http://www.sudone.com/nginx/nginx_url_hash.html
在文檔中是使用 $ request_uri 做因子,稍微改一下 :
hash $http_x_forwarded_for”;
這樣就改成了利用x_forwarded_for這個頭作因子,在nginx新版本中可支援讀取cookie值,所以也可以改成:
hash $cookie_jsessionid;
假如在php中配置的session為無cookie方式,配合nginx自己的一個userid_module模組就可以用nginx自發一個cookie,可參見userid模組的英文文檔:
http://wiki.nginx.org/NginxHttpUserIdModule
另可用姚偉斌編寫的模組upstream_jvm_route:http://code.google.com/p/nginx-upstream-jvm-route/

轉自:http://blog.csdn.net/xluren/article/details/16951247

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.