2009-06-15 146 views
43

好吧,我已經得到了這個完全罕見的負載均衡PHP網站的獨特場景。令人失望的是 - 它以前不是負載平衡的。現在我們開始發現問題了......負載均衡羣集中的PHP會話 - 如何?

目前唯一的問題是PHP會話。當然,最初沒有人想到這個問題,所以PHP會話配置保持其默認值。因此,兩臺服務器都擁有自己的小會話文件,而悲傷的是獲取下一個請求的用戶被拋出到另一臺服務器,因爲他沒有在第一個服務器上創建的會話。

現在,我一直在閱讀如何解決這種情況的PHP手冊。在那裏,我發現了session_set_save_handler()的好功能。 (巧合的是,SO上的this topic)整潔。除了我將不得不在網站的所有頁面中調用此函數。未來頁面的開發人員也必須記得隨時調用它。感覺有點笨拙,更不用說可能違反了一打最好的編碼習慣。如果我只需要翻轉一些全局配置選項和Voilà - 這些會話都會神奇地存儲在數據庫或內存緩存中或其他內容中,那將會更好。

有關如何做到這一點的任何想法?


補充:澄清 - 我希望這是一個標準的解決方案標準的情況。僅供參考 - 我有一個MySQL數據庫可用。當然,必須有一些現成的代碼可以解決這個問題嗎?當然,我可以寫我自己的會話保存的東西, Greg指出的 auto_prepend選項似乎很有前途 - 但這會讓人覺得重新發明輪子。 :P
添加2:負載平衡DNS基礎。我不知道這是如何工作的,但我想這應該是像 this
新增3: OK,我看到一個解決方案是使用 auto_prepend選項在每個腳本插入到 session_set_save_handler()打個電話,寫我自己的DB留存,也許在調用 memcached扔有更好的表現。很公平。

是否還有一些方法可以避免自己編碼這一切?就像一些着名且經過充分測試的PHP插件一樣?

增加了很多,很久以後:這是我到底去的方式:How to properly implement a custom session persister in PHP + MySQL?

而且,我只是手動包括會話處理器中的所有頁面。

回答

31

您可以設置PHP來處理數據庫中的會話,從而爲所有的服務器使用相同的數據庫所有服務器共享相同的會話信息。

一個很好的教程可以是found here

+5

這不是正確的方法。問題是PHP會話,忘記數據庫,我們正在談論PHP。這個解決方案只是一個解決方法。 – Daniel 2011-12-14 13:37:16

3

要做的最簡單的事情就是配置您的負載均衡器始終將同一會話發送到同一臺服務器。

如果你仍然想使用session_set_save_handler那麼也許看看的auto_prepend。

+0

負載平衡是用DNS條目完成的。主機名解析爲兩個不同的IP地址,瀏覽器隨機選擇一個。或者類似的東西 - 我真的不知道詳情。但是AFAIK沒有負載均衡器。 「auto_prepend」看起來很有前途。 – 2009-06-15 08:14:14

+0

+1使用auto_prepend在每個腳本之前插入session_set_save_handler函數 – Galen 2009-06-15 08:41:03

+2

聽起來就像您在旅途中有一個「Round Robin DNS」 - http://en.wikipedia.org/wiki/Round_robin_DNS。我會說,至少說這個「解決方案」負載平衡,更好。 – Ian 2009-06-15 08:54:44

1

當我們遇到這種情況時,我們實現了一些生活在共同標題中的代碼。

本質上,我們檢查每個頁面是否知道會話標識。如果我們不檢查我們是否處於您描述的情況,那麼通過檢查我們是否在DB中存儲了sesion數據。否則,我們只是開始一個新的會話。

顯然,這需要將複製到數據庫中的所有相關數據,但如果你封裝在一個單獨的類會話數據,然後它工作正常。

6

你沒有提到你用於負載平衡的技術(軟件,硬件等);但無論如何,解決您的問題的方法是在負載均衡器上使用「粘性會話」。總而言之,這意味着當來自「新」訪問者的第一個請求進入時,它們被分配到集羣中的特定服務器:所有未來對其會話生命週期的請求將被髮送到該服務器。實際上,這意味着在單個服務器上編寫的應用程序可以通過零/少量代碼更改擴展到平衡的環境。

如果您使用的是硬件平衡器(例如Radware設備),那麼粘性會話將配置爲羣集設置的一部分。硬件設備通常會爲您提供更加細緻的控制:例如分配給新用戶的服務器(他們可以檢查健康狀況等,選擇最健康/最少使用的服務器),以及更多地控制服務器失敗並退出羣集。硬件平衡器的缺點是成本 - 但它們是值得的。

至於軟件平衡器,它歸結爲你正在使用的。對於Apache有上的mod_proxy的stickysession財產 - 的通過谷歌的文章和大量的獲得與PHP會話(for example


編輯這個工作: 從原來的問題之後發佈的其他意見,這聽起來像你「平衡」是通過循環DNS完成的,因此上述可能不適用。我會避免進一步評論,並開始對循環賽DNS的火焰。

+0

我沒有選擇這個解決方案,我也不能改變它。 – 2009-06-15 09:02:35

1

你也可以嘗試使用內存緩存的會話處理程序

1

如果您使用的是php會話,您可以使用NFS共享集羣中所有服務器之間的/ tmp目錄,我認爲這些會話是存儲的。這樣你就不需要數據庫。

編輯:您也可以使用外部服務,如memcachedb(持久和快速),並將會話信息存儲在memcachedb索引中,並使用內容的哈希或甚至會話ID對其進行標識。

17

我們處理這個問題的方式是通過memcached。它所需要的是改變類似於以下php.ini中:

session.save_handler = memcache 
session.save_path = "tcp://path.to.memcached.server:11211" 

我們使用AWS ElastiCache,所以服務器的路徑是一個域名,但我敢肯定,這將會是本地的memcached類似的爲好。

此方法不需要任何應用程序代碼更改。

1

如果你有時間,你還是要檢查更多的解決方案,看看 http://redis4you.com/articles.php?id=01 ..

使用Redis的你是容錯。從我的角度來看,由於這種穩健性,它可能比memcache解決方案更好。

0

可能爲時已晚,但檢查了這一點:http://www.pureftpd.org/project/sharedance

Sharedance是一個高性能的服務器來集中臨時密鑰/數據在遠程主機上 對,沒有開銷和一個SQL 的複雜性數據庫。

它主要用於共享服務器池之間的緩存和會話。通過一個簡單的PHP API訪問共享服務器是微不足道的,它與PHP 4和PHP 5會話處理程序的期望兼容。

0

當涉及到負載平衡羣集中的php會話處理時,最好有粘滯會話。爲此要求正在維護負載均衡器的數據中心網絡啓用粘滯會話。一旦啓用,你將不需要擔心在php端會話