在平常運維工做中,當給Web站點使用負載均衡以後,必須面臨的一個重要問題就是Session的處理辦法,不管是PHP、Python、Ruby仍是Java語言環境,只要使用服務器保存Session,在作負載均衡時都須要考慮Session的問題。php
一般面臨的問題nginx
從用戶端來解釋,就是當一個用戶第一次訪問被負載均衡代理到後端服務器A並登陸後,服務器A上保留了用戶的登陸信息;當用戶再次發送請求時, 根據負載均衡策略可能被代理到後端不一樣的服務器,例如服務器B,因爲這臺服務器B沒有用戶的登陸信息,因此致使用戶須要從新登陸。這對用戶 來講是不可忍受的。因此,在實施負載均衡的時候,咱們必須考慮Session的問題。 在負載均衡中,針對Session的處理,通常有如下幾種方法: 1)Session會話保持(案例:Nginx、Haproxy) 2)Session會話複製(案例:Tomcat) 3)Session會話共享(案例:Memcached、Redis)
1、Session會話保持web
Session保持(會話保持)是咱們見到最多的名詞之一,經過會話保持,負載均衡進行請求分發的時候保證每一個客戶端固定的訪問到後端的同一臺應用服務器。 會話保持方案在全部的負載均衡都有對應的實現。並且這是在負載均衡這一層就能夠解決Session問題。 ================Nginx 作負載均衡的Session保持================ 對於Nginx能夠選用Session保持的方法實行負載均衡,nginx的upstream目前支持5種方式的分配方式,其中有兩種比較通用的Session解決方法,ip_hash和url_hash。 注意:後者不是官方模塊,須要額外安裝。 ip_hash 每一個請求按訪問ip的hash結果分配,這樣每一個訪客固定訪問一個後端服務器,達到了Session保持的方法。 例: upstream bakend { ip_hash; server192.168.0.11:80; server192.168.0.12:80; } ================Haproxy作負載均衡的Session保持================ Haproxy做爲一個優秀的反向代理和負載均衡軟件,也提供了多種Session保持的方法,下面列舉了兩種最經常使用的: 1) 源地址 Hash haroxy 將用戶IP通過hash計算後指定到固定的真實服務器上(相似於nginx 的ip hash 指令) 配置指令:balancesource 2)使用cookie 進行識別 也就是Haproxy在用戶第一次訪問的後在用戶瀏覽器插入了一個Cookie,用戶下一次訪問的時候瀏覽器就會帶上這個Cookie給Haproxy,Haproxy進行識別。 配置指令:cookie SESSION_COOKIE insert indirect nocache 配置例子以下: cookie SERVERID insert indirect nocache server web01 192.168.56.11:8080 check cookie web01 server web02 192.168.56.12:8080 check cookie web02 =========================================================== 會話保持的缺點: 1) 會話保持看似解決了Session同步的問題,可是卻帶來的一些其它方面的問題: 2)負載不均衡了:因爲使用了Session保持,很顯然就沒法保證負載絕對的均衡。 3)沒有完全解決問題:若是後端有服務器宕機,那麼這臺服務器的Session丟失,被分配到這臺服務請求的用戶仍是須要從新登陸。
2、Session會話保持redis
既然,咱們的目標是全部服務器上都要保持用戶的Session,那麼將每一個應用服務器中的Session信息複製到其它服務器節點上是否是就能夠呢? 這就是Session的第二中處理辦法:會話複製。 會話複製在Tomcat上獲得了支持,它是基於IP組播(multicast)來完成Session的複製,Tomcat的會話複製分爲兩種: 1)全局會話複製:利用Delta Manager複製會話中的變動信息到集羣中的全部其餘節點。 2)非全局複製:使用Backup Manager進行復制,它會把Session複製給一個指定的備份節點。 不過,這裏不許備來解釋會話複製的Tomcat配置,若是有需求能夠參考Tomcat官方文檔,主要是由於會話複製不適合大的集羣。根據生產的實踐案例, 在集羣超過6個節點以後就會出現各類問題,不推薦生產使用。
3、Session會話共享sql
既然會話保持和會話複製都不完美,那麼咱們爲何不把Session放在一個統一的地方呢,這樣集羣中的全部節點都在一個地方進行Session的存取就能夠解決問題。 ========================================================================================= Session存放到哪裏? 對於Session來講,確定是頻繁使用的,雖然你能夠把它存放在數據庫中,可是真正生產環境中我更推薦存放在性能更快的分佈式KV數據中, 例如:Memcached和Redis。 --------------------------------------------------------------- PHP設置Session共享 若是使用的是PHP那麼恭喜你,配置很是的簡單。PHP經過兩行配置就能夠把Session存放在Memcached或者Redis中,固然你要提早配置好他們。修改php.ini: 使用Memcache存儲Session session.save_handler = memcache session.save_path = "tcp://192.168.56.11:11211" 使用Redis存儲Session session.save_handler = redis session.save_path ="tcp://localhost:6379" 提醒:別忘了給PHP安裝memcache或者redis插件。 --------------------------------------------------------------- Tomcat設置Session共享 可使用MSM(Memcached Session Manager)來實現一樣把Session存放到Memcache中。 --------------------------------------------------------------- Django設置Session共享 在Django中Session是經過一箇中間件管理的。若是要在應用程序中使用Session,須要在settings.py中的MIDDLEWARE_CLASSES變量中加入 'django.contrib.sessions.middleware.SessionMiddleware' 。Django的Session引擎能夠將Session存放在三個地方,分別是:數據庫、緩存、文件。 --------------------------------------------------------------- 若是你想使用數據庫支持的會話,你須要添加’django.contrib.sessions’到你的INSTALLED_APPS設置中。在配置完成以後,請運行manage.py migrate 來安裝保存會話數據的一張數據庫表。 --------------------------------------------------------------- 使用緩存保持Session 對於簡單的緩存會話: 能夠設置SESSION_ENGINE 爲」django.contrib.sessions.backends.cache」。此時會話數據將直接存儲在你的緩存中。然而,緩存數據將可能不會持久: 若是緩存填滿或者緩存服務器重啓,緩存數據可能會被清理掉。 若要持久的緩存數據: 能夠設置SESSION_ENGINE爲」django.contrib.sessions.backends.cached_db」。它的寫操做使用緩存,對緩存的每次寫入都將再寫入到數據庫。對於 讀取的會話,若是數據不在緩存中,則從數據庫讀取。兩種會話的存儲都很是快,可是簡單的緩存更快,由於它放棄了持久性。大部分狀況下,cached_db後端已經足夠快,可是若是你須要榨乾最後一點的性能,而且接受會話數據丟失的風險,那麼你可以使用cache而不是cached_db 使用文件保存Session 使用文件保存Session再也不咱們的討論之類,由於很難進行共享,PHP默認也是將Session存放在/tmp目錄下。
簡單總結:數據庫