今天就跟大家聊聊有關(guān)Spring Session redis 在不同服務(wù)間共享 Session 時(shí)的類共享方案的示例分析,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
建網(wǎng)站原本是網(wǎng)站策劃師、網(wǎng)絡(luò)程序員、網(wǎng)頁(yè)設(shè)計(jì)師等,應(yīng)用各種網(wǎng)絡(luò)程序開發(fā)技術(shù)和網(wǎng)頁(yè)設(shè)計(jì)技術(shù)配合操作的協(xié)同工作。成都創(chuàng)新互聯(lián)專業(yè)提供成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、成都外貿(mào)網(wǎng)站建設(shè),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站制作(企業(yè)站、自適應(yīng)網(wǎng)站建設(shè)、電商門戶網(wǎng)站)等服務(wù),從網(wǎng)站深度策劃、搜索引擎友好度優(yōu)化到用戶體驗(yàn)的提升,我們力求做到極致!
當(dāng)在多服務(wù)之間使用 Spring Session Redis 進(jìn)行 Session 共享要非常小心,因?yàn)樗懿话踩苡锌赡軐?dǎo)致整個(gè)服務(wù)實(shí)例不可用,無(wú)法處理任何請(qǐng)求。其中比較危險(xiǎn)的地方就是在進(jìn)行序列化,反序列化的時(shí)候(這種類型的錯(cuò)誤尤其容易在沒有開發(fā)規(guī)范的團(tuán)隊(duì)內(nèi)發(fā)生,就是什么樣的數(shù)據(jù)可以往共享存儲(chǔ)里面存,什么樣的不能存。存的時(shí)候要以什么樣的格式去存,這些都要有規(guī)定才比較安全。因?yàn)楣蚕泶鎯?chǔ)是會(huì)影響到別人的不僅僅是為了自己的服務(wù)用起來(lái)方便)。RedisSerializer 接口的實(shí)現(xiàn)都是在序列化和反序列化出錯(cuò)的時(shí)候直接拋出異常從而導(dǎo)致整個(gè)請(qǐng)求錯(cuò)誤。
public interface RedisSerializer{ /** * Serialize the given object to binary data. * * @param t object to serialize * @return the equivalent binary data */ byte[] serialize(T t) throws SerializationException; /** * Deserialize an object from the given binary data. * * @param bytes object binary representation * @return the equivalent object instance */ T deserialize(byte[] bytes) throws SerializationException; }
下面用一張圖來(lái)說(shuō)明我遇到的問(wèn)題。Spring Session 的誕生老實(shí)說(shuō)并不是為了分布式系統(tǒng),而是為集群系統(tǒng)提供了一種 Session 解決方案。但是我們把 Spring Session 用在了分布式系統(tǒng)上用以解決 Session 共享的問(wèn)題老實(shí)說(shuō)本身就是有點(diǎn)難為人家 Spring Session 了 。
Spring Session 實(shí)現(xiàn) Session 共享的大致原理如下圖所示 , 使用一個(gè) Filter 來(lái)攔截所有請(qǐng)求,在攔截到請(qǐng)求之后對(duì) HttpServletRequest 和 HttpServletResponse 進(jìn)行包裝 (HttpServletRequestWrapper , HttpServletResponseWrapper)。在包裝中對(duì) session 進(jìn)行控制 ,將 session 數(shù)據(jù)都存儲(chǔ)在第三方存儲(chǔ)當(dāng)中。
在了解了 Spring Session 的工作原理后再去考慮這個(gè)問(wèn)題就有頭緒了 。還是通過(guò)圖形的方式來(lái)做大概的說(shuō)明。
學(xué)習(xí) Spring Session 的 SessionRepositoryFilter 的實(shí)現(xiàn)方式 , 添加一個(gè) Filter 順序在 SessionRepositoryFilter 之后 , 在攔截過(guò)程中包裝 HttpServletRequest , 重寫 getSession(boolean create) 和 getSession() 方法, 自定義一個(gè) SafetyHttpSessionWrapper 包裝 Session ,重寫 setAttribute(String name , Object value) 函數(shù) , 在保存屬性成功后利用 redis 的發(fā)布訂閱機(jī)制發(fā)送消息到 redis , 消息的內(nèi)容為所保存對(duì)象的 .class 文件數(shù)據(jù)。在消息訂閱端 , 接收到消息后利用 javassist 和 net.bytebuddy.dynamic.loading.ByteArrayClassLoader 將 .class 文件數(shù)據(jù)加載轉(zhuǎn)換成 Class 的實(shí)例對(duì)象,但是這個(gè) Class 實(shí)例的范圍被限定在 ByteArrayClassLoader 中 , 而這個(gè) ByteArrayClassLoader 是提供給 RedisSerializer 內(nèi)部使用的 , 比如 JdkSerializationRedisSerializer , GenericJackson2JsonRedisSerializer 都需要使用到 ClassLoader 。這樣當(dāng) 服務(wù)A 在存儲(chǔ)任何自定義的對(duì)象在 Session 中時(shí), 訪問(wèn)服務(wù) B 也不會(huì)出現(xiàn)讀取 Session 反序列化 ClassNotFoundException 的錯(cuò)誤了。
看完上述內(nèi)容,你們對(duì)Spring Session Redis 在不同服務(wù)間共享 Session 時(shí)的類共享方案的示例分析有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。