在網站使用nginx+php作負載均衡狀況下,同一個IP訪問同一個頁面會被分配到不一樣的服務器上,若是session不一樣步的話,就會出現不少問題,好比說最多見的登陸狀態。php
下面羅列幾種nginx負載均衡中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的安全性不高,雖然它已經加了密,可是仍是能夠僞造的。mysql
2)session存在數據庫(MySQL)中
PHP能夠配置將session保存在數據庫中,這種方法是把存放session的表和其餘數據庫表放在一塊兒,若是mysql也作了集羣的話,每一個mysql節點都要有這張表,而且這張session表數據表要實時同步。
可是要注意的是:
用數據庫來同步session,會加大數據庫的IO,增長數據庫的負擔。並且數據庫讀寫速度較慢,不利於session的適時同步。linux
3)session存在memcache或者redis中
memcache能夠作分佈式,php配置文件中設置存儲方式爲memcache,這樣php本身會創建一個session集羣,將session數據存儲在memcache中。
特別說明:
以這種方式來同步session,不會加大數據庫的負擔,而且安全性比用cookie大大的提升,把session放到內存裏面,比從文件中讀取要快不少。可是memcache把內存分紅不少種規格的存儲塊,有塊就有大小,這種方式也就決定了,memcache不能徹底利用內存,會產生內存碎片,若是存儲塊不足,還會產生內存溢出。nginx
4)採用nginx中的ip_hash機制
nginx中的ip_hash技術可以將某個ip的請求定向到同一臺後端web機器中,這樣一來這個ip下的某個客戶端和某個後端web機器就能創建起穩固的session。
也就是說,ip_hash機制可以讓某一客戶機在至關長的一段時間內只訪問固定的後端的某臺真實的Web服務器,這樣會話就會得以保持,咱們在網站頁面進行login的時候,
就不會在後面的web服務器之間跳來跳去了,天然也不會出現登錄一次後網站又提醒你沒有登錄須要從新登錄的狀況;web
ip_hash是在upstream配置中定義的:redis
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這個因子來分配後端web,所以ip_hash是有缺陷的,不能在一些狀況下使用:
a)nginx不是最前端的服務器。
ip_hash要求nginx必定是最前端的服務器,不然nginx得不到正確ip,就不能根據ip做hash。譬如使用的是squid爲最前端,那麼nginx取ip時只能獲得squid的服務器ip地址,用這個地址來做分流是確定錯亂的。
b)nginx的後端還有其它方式的負載均衡。
假如nginx後端又有其它負載均衡,將請求又經過另外的方式分流了,那麼某個客戶端的請求確定不能定位到同一臺session應用服務器上。這麼算起來,nginx後端只能直接指向應用服務器,或者再搭一個squid,而後指向應用服務器。最好的辦法是用 location做一次分流,將須要session的部分請求經過ip_hash分流,剩下的走其它後端去。sql
----------------------------順便說一下以前線上用過的nginx負載均衡中的session共享處理方案---------------------------- 用的就是上面第三站方式,將session存放在memcached裏面。 公司的一些網站頁面(LNMP框架)涉及到登錄需求(有sessionID),用到了memcache緩存服務,將php的sessionID緩存到memcache裏面。 將sessionID放在memcache裏後,會加快頁面訪問速度,頁面訪問飛快! 若是memcache裏面存放的只是sessionID,而沒有其餘業務,那麼memcache服務器的內存消耗就不大! 首先保障php擴展模塊裏要支持memcached功能(即必定要安裝php的memcached擴展模塊) [root@huanqiu vhosts]# /Data/app/php5.5.1/bin/php -m [PHP Modules] .......... memcached ........... 遇到問題: 在遷移網站業務的過程當中(遷移後使用的是新的memcache機器) 因爲php.ini和代碼中的memcache鏈接信息沒有及時修改或者沒有徹底修改過來,致使遷移後的頁面訪問速度有點緩慢,有點卡! 最後仔細排查,把全部有關memcache鏈接信息的配置都改過來了,遷移後的頁面訪問速度就正常了! 1)首先部署三臺memcache服務器,主機名分別是memcache1.server ,memcache2.server ,memcache3.server ,啓動相應的端口。 注意,不用業務應用到的memcache服務端口不能衝突。 好比:業務A用到memcache1-3.server服務器的11021,11022,11023端口,業務B就用到了memcache1-3.server的11031,11032,11033端口 部署memcache集羣服務 yum安裝便可,部署三臺memcache1,memcache2,memcache3 啓動相應緩存端口 [root@memcache2 ~]# ps -ef|grep memcache root 6139 1 0 May30 ? 00:00:05 /usr/bin/memcached -d -m 512 -p 11021 -u root -c 4096 -P /var/lib/memcache/logs/memcached_11021.pid root 6184 1 0 May30 ? 00:00:05 /usr/bin/memcached -d -m 512 -p 11022 -u root -c 4096 -P /var/lib/memcache/logs/memcached_11022.pid root 6198 1 0 May30 ? 00:00:05 /usr/bin/memcached -d -m 512 -p 11023 -u root -c 4096 -P /var/lib/memcache/logs/memcached_11023.pid root 6214 1 0 May30 ? 00:00:05 /usr/bin/memcached -d -m 512 -p 11031 -u root -c 4096 -P /var/lib/memcache/logs/memcached_11031.pid root 6229 1 0 May30 ? 00:00:05 /usr/bin/memcached -d -m 512 -p 11032 -u root -c 4096 -P /var/lib/memcache/logs/memcached_11032.pid root 6244 1 0 May30 ? 00:00:05 /usr/bin/memcached -d -m 512 -p 11033 -u root -c 4096 -P /var/lib/memcache/logs/memcached_11033.pid 將上面的程序添加到開機啓動/etc/rc.local裏面 2)在業務機器上應用memcache緩存 a)好比業務A 首先在相應的業務服務器上的/etc/hosts裏設置主機映射(若是能ping通memcache機器的內網,就用內網) #vim /etc/hosts 192.168.1.23 memcache1.server 192.168.1.24 memcache2.server 192.168.1.25 memcache3 .server 首先在php的php.ini裏面設置memcache緩存 #vim /Data/app/php/etc/php.ini ............... [Session] session.save_handler = memcached session.save_path = "memcache1.server :11021,memcache2.server :11022,memcache3.server :11023" 而後重啓php服務 最後在相應的代碼程序裏使用memcache緩存,好比: # vim main.php $config['params']['erp_host'] = 'http://www.xqshijie.com'; //如下是memcache配置,把相應的參數都換成相應環境下的 $config['components']['cache']['class'] = 'system.caching.CMemCache'; $config['components']['cache']['useMemcached'] = 'true'; $config['components']['cache']['keyPrefix'] = ''; $config['components']['cache']['hashKey'] = false; $config['components']['cache']['serializer'] = false; $config['components']['cache']['servers'][0]['host'] = 'memcache1.server'; $config['components']['cache']['servers'][0]['port'] = 11021; $config['components']['cache']['servers'][0]['weight'] = 10; ........................... b)業務B 在相應業務服務器的/etc/hosts裏設置主機映射(若是能ping通memcache機器的內網,就用內網) #vim /etc/hosts 192.168.1.23 memcache1.server 192.168.1.24 memcache2.server 192.168.1.25 memcache3 .server 首先在php的php.ini裏面設置memcache緩存 #vim /Data/app/php/etc/php.ini ............... [Session] session.save_handler = memcached session.save_path = "memcache1.server :11031,memcache2.server :11032,memcache3.server :11033" 而後重啓php服務 最後在相應的代碼程序裏使用memcache緩存,好比: # vim main.php $config['params']['erp_host'] = 'http://erp.fangfull.com'; //如下是memcache配置,把相應的參數都換成相應環境下的 $config['components']['cache']['class'] = 'system.caching.CMemCache'; $config['components']['cache']['useMemcached'] = 'true'; $config['components']['cache']['keyPrefix'] = ''; $config['components']['cache']['hashKey'] = false; $config['components']['cache']['serializer'] = false; $config['components']['cache']['servers'][0]['host'] = 'memcache1.server'; $config['components']['cache']['servers'][0]['port'] = 11031; $config['components']['cache']['servers'][0]['weight'] = 10; ............................................. -------------------------------------------------------------------------------------------------- 清理memcache緩存的方法: 1) 默認memcache會監聽11221端口,若是想清空服務器上memecache的緩存,你們通常使用的是: telnet localhost 11211 flush_all 2)一樣也可使用: echo "flush_all" | nc localhost 11211 使用flush_all 後並非刪除memcache上的key,而是置爲過時
------------------------------------php.ini中關於session屬性的相關設置-------------------------------------
1)
session.use_cookies:是否在客戶端用 cookie 來存放會話 ID,1是開啓 ,0是關閉
若session.use_cookies = 1
sessionid在客戶端採用的存儲方式,置1表明使用cookie記錄客戶端的sessionid,同時,$_COOKIE變量裏纔會有$_COOKIE[‘PHPSESSIONID’]這個元素存在數據庫
通常腳本語言都會原生支持「session機制」,如PHP程序配置:
設置php.ini的session.use_trans_sid = 1,PHP自動在URL裏傳遞session id
設置php.ini的session.use_cookies = 1,使用cookie在客戶端保存session idapache
2)
session.auto start:
將php.ini中的以下選項配置修改便可:
session.auto_start=0
修改爲
sessioin.auto_start=1
開啓session.auto_start
優勢在於,任什麼時候候都不會因忘記執行session_start()或session_start()在程序裏的位置不對,而致使錯誤;
缺點在於,若是你使用的是第三方代碼,則必須刪去其中的所有 session_start(),不然將不能獲得正確的結果。
3)
session的內容存在文件裏的話,文件在哪兒?
若是不指定, Linux下默認在 "/tmp"目錄。
線上在php.ini配置文件了作了指定,session內容存放在memcache緩存裏。
默認session內容是存儲在文件裏的,即session.save_handler = files
可是咱們線上是設置將session內容保存到memcache裏的
線上環境下的配置:
[Session]
; Handler used to store/retrieve data.
; http://php.net/session.save-handler
;session.save_handler = files
session.save_handler = memcached
session.save_path = "memcache1.huanqiu.com:11311,memcache1.huanqiu.com:11312,memcache2.huanqiu.com:11311,memcache2.huanqiu.com:11312"
4)
session的生命週期的設置
a)session的默認生命週期是多久?
答:關閉瀏覽器就失效
緣由:由於session_id存在於cookie,而默認狀況,cookie關閉瀏覽器即失敗.
b)如何設置session生命週期爲30分鐘呢?
在php.ini文件裏設置session.cookie_lifetime = 1800
線上生產環境下設置的是7天,生命週期是一週
; Lifetime in seconds of cookie or, if 0, until browser is restarted.
; http://php.net/session.cookie-lifetime
session.cookie_lifetime = 604800
5)
session的名字
; Name of the session (used as cookie name).
; http://php.net/session.name
session.name = PHPSESSID
------------------------------------------session與cookie的簡單區別-----------------------------------------
session和cookie本質上確實是兩個東西,但cookie同時也是session id的載體,cookie保存session id。
1)cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。
session保存在服務器端與瀏覽器設置無關,cookie在客戶端並受瀏覽器設置限制。
cookie是在你的電腦上保存的,session是在服務器上的. 也就是說你換一個電腦你的cookie就不起做用了, 而session只要你的瀏覽器不關就還能訪問到. 一般的都是二者結合着用的. cookie的話你本身就能夠經過對瀏覽器的設置禁用掉.這樣就不起做用了
2)cookie不是很安全,別人能夠分析存放在本地的cookie並進行cookie欺騙,考慮到安全應當使用session。
session是服務器端緩存,cookie是客戶端緩存。
cookie機制採用的是在客戶端保持狀態的方案,而session機制採用的是在服務器端保持狀態的方案
3)session會在必定時間內保存在服務器上。當訪問增多,會比較佔用你服務器的性能,考慮到減輕服務器性能方面,應當使用cookie。
session是服務器保持客戶端狀態信息的方案,通常是保存在服務器中的一塊內存中,session超時時間在服務器端進行設置。
cookie是客戶端保持用戶信息的方案,通常是文件形式保存,cookie清空時間是在客戶端瀏覽器設置。
從開發角度說,session信息能夠經過技術方案寫到客戶端保存,cookie中的用戶信息,也能夠在用戶訪問該網站時,經過技術手段自動更新用戶的session信息。
4)單個cookie保存的數據不能超過4K,不少瀏覽器都限制一個站點最多保存20個cookie。
5)建議:將登錄信息等重要信息存放爲session;其餘信息若是須要保留,能夠放在cookie中
-------------------------------------------開啓session功能----------------------------------------
開啓session功能是很重要的,好比下面一個場景:某個網站程序在測試服務器上調試,首頁是ok的,但一到後臺去登陸就登陸不進去,起初懷疑是rewrite規則沒有寫對,後排查就是由於session功能沒有打開引發的!
那麼session應該如何開啓?
1)編輯php.ini配置文件
session.save_path=文件夾路徑 指向任意一個有寫權限的目錄就好了.
register_globals = On 打開全局變量,若是不打開,你就這樣用$_SESSION['sessioname'];可是我本人歷來沒成功過.
2)重啓php服務便可(若是是lamp模式,就重啓apache)
-----------------------------------------看一個linux下Session丟失的案例分析----------------------------------------
因爲各類緣由須要進行代碼遷移,遷移後從新搭建php環境,運行代碼。最後在登陸頁面時發現後臺不能訪問,會直接返回到登陸頁面,接着對代碼進行測試,沒有報任何錯誤,最後排查是由於跳轉時session丟失形成的!那麼session如何會丟失呢?
發現形成這個緣由有這幾種:
a)session存儲路徑(目錄)不存在,天然就沒法生成session臨時文件
b)session存儲路徑下有沒有權限,若是沒有,也就不可能存儲session數據
c)能正常存session數據,但session存入後被清空
嘗試解決的措施:
a)在項目根目錄下建立phpinfo.php文件,在文件中寫入phpinfo(),運行此文件,查看頁面,就能夠找到session的存儲路徑,
b)在服務器上查找session存儲路徑是否存在,不存在建立存儲目錄,並分配權限,若是有session存儲路徑,就查看其是否有權限,沒有就分配權限,
c)是不是第三個緣由,可在phpinfo.php頁面中查找date.timezone是否設置不對,而後在php.ini配置文件中找到date.timezone進行配置
-------------------------------------------------------------------------------------------------------------------
須要清楚知道的:
1)上面在php.ini文件裏將session.save_handler修改成memcached,即表示將php的session信息存放到memcache裏(前提是安裝了memcached擴展),而後在session.save_path處配置鏈接memcache信息。如:
session.save_handler = memcached
session.save_path = "memcache1.huanqiu.com:11311,memcache1.huanqiu.com:11312,memcache2.huanqiu.com:11311,memcache2.huanqiu.com:11312"
注意:
帶d的memcached擴展,則session.save_path配置鏈接的時候不須要加tcp://
若是是不帶d的memcache擴展,則session.save_path配置鏈接的時候須要加tcp://
2)若是將session.save_handler修改成redis,即表示將php的session信息存放到redis裏(前提是安裝了php的phpredis擴展),而後在session.save_path處配置redis的connect 地址。以下:
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"
-------------------------------------------------------------------------------------------------------------------