解決nginx負載均衡的session共享問題

查了一些資料,看了一些別人寫的文檔,總結以下,實現nginx session的共享php

PHP服務器有多臺,用nginx作負載均衡,這樣同一個IP訪問同一個頁面會被分配到不一樣的服務器上,若是session不一樣步的話,就會出現不少問題,好比說最多見的登陸狀態,下面提供了幾種方式來解決session共享的問題:前端

一、不使用session,換用cookie

session是存放在服務器端的,cookie是存放在客戶端的,咱們能夠把用戶訪問頁面產生的session放到cookie裏面,就是以cookie爲中轉站。你訪問web服務器A,產生了session而後把它放到cookie裏面,當你的請求被分配到B服務器時,服務器B先判斷服務器有沒有這個session,若是沒有,再去看看客戶端的cookie裏面有沒有這個session,若是也沒有,說明session真的不存,若是cookie裏面有,就把cookie裏面的sessoin同步到服務器B,這樣就能夠實現session的同步了。java

說明:這種方法實現起來簡單,方便,也不會加大數據庫的負擔,可是若是客戶端把cookie禁掉了的話,那麼session就無從同步了,這樣會給網站帶來損失;cookie的安全性不高,雖然它已經加了密,可是仍是能夠僞造的。mysql

二、session存在數據庫(MySQL等)中

PHP能夠配置將session保存在數據庫中,這種方法是把存放session的表和其餘數據庫表放在一塊兒,若是mysql也作了集羣了話,每一個mysql節點都要有這張表,而且這張session表的數據表要實時同步。linux

說明:用數據庫來同步session,會加大數據庫的IO,增長數據庫的負擔。並且數據庫讀寫速度較慢,不利於session的適時同步。nginx

三、session存在memcache或者redis中

memcache能夠作分佈式,php配置文件中設置存儲方式爲memcache,這樣php本身會創建一個session集羣,將session數據存儲在memcache中。web

說明:以這種方式來同步session,不會加大數據庫的負擔,而且安全性比用cookie大大的提升,把session放到內存裏面,比從文件中讀取要快不少。可是memcache把內存分紅不少種規格的存儲塊,有塊就有大小,這種方式也就決定了,memcache不能徹底利用內存,會產生內存碎片,若是存儲塊不足,還會產生內存溢出。redis

四、ip_hash

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

upstream nginx.example.com  
    {   
             server 192.168.74.235:80;   
             server 192.168.74.236:80;  
             ip_hash;  
    }  
    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分流,剩下的走其它後端去。

五、upstream_hash
爲了解決ip_hash的一些問題,可使用upstream_hash這個第三方模塊,這個模塊多數狀況下是用做url_hash的,可是並不妨礙將它用來作session共享。沒試過真心的不明白

補充:memcached簡單的介紹

1、概念

Memcached是danga.com(運營LiveJournal的技術團隊)開發的一套分佈式內存對象緩存系統,用於在動態系統中減小數據庫負載,提高性能。

2、適用場合

1.      分佈式應用。因爲memcached自己基於分佈式的系統,因此尤爲適合大型的分佈式系統。

2.      數據庫前段緩存。數據庫經常是網站系統的瓶頸。數據庫的大併發量訪問,經常形成網站內存溢出。固然咱們也可使用Hibernate的緩存機制。但memcached是基於分佈式的,並可獨立於網站應用自己,因此更適合大型網站進行應用的拆分。

3.      服務器間數據共享。舉例來說,咱們將網站的登陸系統、查詢系統拆分爲兩個應用,放在不一樣的服務器上,並進行集羣,那這個時候用戶登陸後,登陸信息如何從登陸系統服務器同步到查詢系統服務器呢?這時候,咱們即可以使用memcached,登陸系統將登陸信息緩存起來,查詢系統即可以得到登陸信息,就像獲取本地信息同樣。

3、不適用場合

那些不須要「分佈」的,不須要共享的,或者乾脆規模小到只有一臺服務器的應用,memcached不會帶來任何好處,相反還會拖慢系統效率,由於網絡鏈接一樣須要資源

 

解決方案,使用memcached作爲session的存儲,memcached服務器設置在和nginx同一臺linux主機上。

解決過程,

兩臺apache的主機IP分別是 192.168.74.235192.168.74.236

Nginx主機IP是192.168.74.131

Memcached主機的IP是192.168.74.131

在192.168.74.131 安裝memcached,而且啓動

以一臺爲例192.168.74.236,安裝php及php對memcached的依賴庫yuminstall memcached-devel.i686 libmemcached-devel.i686  php-pecl-memcache.i686

配置php.ini

session.save_handler= memcache

session.save_path= "tcp://192.168.74.131:11211"

或者(如下兩個沒有嘗試)

1.某個目錄下的 .htaccess :

php_value session.save_handler "memcache"
php_value session.save_path  "tcp://IP:11211"

2.在某個一個應用中:

ini_set("session.save_handler", "memcache");
ini_set("session.save_path", "tcp://IP:11211"); 

 

同時必定要把下面的;session.save_path= "/var/lib/php/session" 註釋掉

同時把extension=memcache.so 打開

重啓一下 apache,查看 phpinfo 中的 "Registered save handlers" 會有 "files usermemcache" 這3個可用,若是有就證實裝好了

Memcached服務器執行及結果

[root@Git ~]# memcached-tool127.0.0.1:11211

 #  Item_Size  Max_age  Pages   Count   Full? Evicted Evict_Time OOM

在236機器上添加下面的php文件

<?php

session_start();

if (!isset($_SESSION['TEST'])) {

   $_SESSION['TEST'] = time();

}

$_SESSION['TEST3'] = time();

print $_SESSION['TEST'];

print "<br><br>";

print $_SESSION['TEST3'];

print "<br><br>";

print session_id();

?>

而後去memcached服務器上執行

[root@Git ~]# memcached-tool127.0.0.1:11211

 #  Item_Size  Max_age  Pages   Count   Full? Evicted Evict_Time OOM

 1      80B         0s       1      0      no        0       0    0

這樣應該就算能夠把session寫到memcached服務器上了。

總結下:

1.      防火牆問題,不少鏈接局域網服務器失敗都是防火牆引發的

2.      依賴沒有安裝完畢,一開始使用memcached總失敗,由於我沒有安裝php-memcached這樣的擴展庫

相關文章
相關標籤/搜索