web專案叢集時共享session方案實踐。
web專案在叢集負載均衡時一個主要的問題就是如何共享session 。 讓多臺機器之間的資料統一。 不能出現使用者在A機器上面登入成功, 之後訪問到B機器的時候提示未登入。
如果使用nginx來實現負載均衡, 它提供了一種hash ip的策略, 將同一個ip的每次請求都轉發到同一臺伺服器上面。 這樣的話, 就不需要共享session了。 但是這樣的壞處是無法讓負載更好的均衡, 可能出現某些機器負載高,有些機器負載低的情況。 所以還是不建議使用這種方式。
下面想到一種負載均衡的思路,就是使用專門一臺快取伺服器來儲存session資訊。
無論在哪臺伺服器登入之後,都將使用者的登入資訊儲存在快取伺服器中。 然後給客戶端設定一個cookie來標識使用者的身份。 來取代jsessionid
快取伺服器可以使用membercached / redis 等記憶體資料庫。
由於前幾天剛好學習了hessian 。 所以決定自己來實現一個快取伺服器 , 並提供介面給其他專案使用。(只簡單的提供了put、get兩個方法)
例項場景
專案1 : cookie-server 快取伺服器
專案2 :cookie-web 普通web專案,實現了登入用例
首先來完成cookie-server (maven)專案。
1、建立cookie-cacheserver-client模組, 用於定義Hessian介面。 一些公共的VO / DTO 物件。
首先定義用於存取資料的介面 CacheService
package cookie.chacheserver.client;
public interface CacheService {
Object getByKey(Object key) ;
boolean put(Object key , Object value) ;
}
然後定義一個LoginUser物件,來表示使用者登入資訊
package cookie.chacheserver.client; import java.io.Serializable; public class LoginUser implements Serializable { /** * */ private static final long serialVersionUID = -2958174180520979633L; private String userId ; private String nick ; public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getNick() { return nick; } public void setNick(String nick) { this.nick = nick; } }
ok 。 cookie-cacheserver-client 模組完成
2、建立cookie-cacheserver-service模組 , 實現cookie-cacheserver-client模組中定義的service
package cookie.cacheserver.service;
import java.util.concurrent.ConcurrentHashMap;
import cookie.chacheserver.client.CacheService;
public class CacheServiceImpl implements CacheService{
private static final ConcurrentHashMap<Object, Object> cacheMap =
new ConcurrentHashMap<Object, Object>() ;
public Object getByKey(Object key) {
return cacheMap.get(key) ;
}
public boolean put(Object key, Object value) {
cacheMap.put(key, value) ;
return cacheMap.containsKey(key) ;
}
}
cookie-cacheserver-service 完成。
3、 建立cookie-cacheserver模組, 來當做 cacheserver的web模組。 來提供服務。
主要來配置hessian通過web的方式啟動。 程式碼不貼了。 可以直接下載專案來看。 專案在文章最後會給出下載連結。
專案結構如圖:
快取伺服器已經完成了 。
接下來做一個web專案。 該專案有主要幾個功能{
1、通過login.jsp頁面進行登入, 通過Login sevlet完成。
Login Servlet 內判斷使用者Id與nick是否符合要求,如果符合要求,就登入成功,並將使用者資訊儲存到快取伺服器上。 然後給瀏覽器設定一個cookie。 將使用者登入標識存入cookie , 然後跳轉到 index servlet 。 在index servlet中會根據使用者cookie中的標識去快取伺服器取出使用者的登入資訊。 然後將資訊展示在index.jsp中。
}
專案就隨便取了個名字cookie-weba , 專案結構如下
專案程式碼下載地址:專案原始碼
兩個專案已經打成war包了。 可以部署到tomcat直接執行。 下載地址:war包
注意:在部署時,最好是將cookie-cacheserver.war 與 cookie-weba.war 分開部署到伺服器上面。
我是在同一臺機器上面測試了。 使用了三個tomcat , 可以將每個tomcat的埠設定成不同 。
tomcat1 使用8080埠來啟動 cookie-cacheserver.war
tomcat2 使用8082埠來啟動cookie-weba.war
tomcat3 使用8083埠,也來啟動cookie-weba.war
登入成功後。 訪問tomcat3的專案。 http://localhost:8083/cookie-webb/index.do , 如果沒有登入, 將會跳轉到login.jsp頁面 。 如果已經登入,就會到index.jsp展示登入資訊。
登入規則是:nike必須以userId字串為開頭。 nick.startsWith(id)