如題,有登陸的系統,舊項目沒cache(我沒權利去加),但是不同的服務都要使用先前http請求到的資料(由使用者區分),想把它保存起來避免每次重複發http請求浪費資源。
後台springmvc
#目前我想到3個方法:
1.丟session裡面(HttpSessionListener),應該最簡單,但不知道潛在問題
2.丟threadlocal裡面(controller搞個static 的threadlocal的變量,或者寫個contextholder)
3.controller搞個ConcurrentHashMap的成員,把資料按<用戶id,http請求拿到的資料>放進去.但是這個肯定不可行,可能會導致堆區OOF
說說第2個方案可能存在的問題。
1.網路上說的可能記憶體外洩問題,導致PermGen出現OOF,原文連接ThreadLocal 記憶體外洩的實例分析
我不確定是否會出現問題(原文有點看不懂),因為ThreadLocalMap的set具有保護機制
2.會不會出現請求線程裡面的資料串了,例如1個請求線程同時服務兩個用戶(A和B)請求,B把自己的資料放到請求線程,覆蓋了A的,而請求線程服務A的時候,拿到了B的資料。 。
方法1是最簡單、最常用的,如果使用者量太大,或是做了負載平衡,就要實現集中儲存的Session,有很多現成的方案可以支援集中儲存的HttpSession的,存Redis、MongoDB、MySQL的都有,GitHub上搜一下。
方法2不解決問題,主要是因為使用者登入後,多次請求可能會落在多個執行緒。你說的第二點也是理由。
方法3也是一種實作方式,其實Tomcat的HttpSession就是用ConcurrentHashMap實現的(只是它用sessionId而不是用userId做key),但要注意的一點是,你必須自己管理Map中每個Key-Value的生命週期,例如Session超時了要及時remove掉。