大廠很多專案都是部署到多台伺服器上,這些伺服器在各個地區都存在,當我們訪問服務時雖然執行的是同一個服務,但是可能是不同伺服器運行的;
在我學習專案時遇到這樣一個登入情景,假設有如下三台伺服器(如圖),就使用session存放使用者的登入信息,透過該資訊可以判斷使用者是否登入:
假設本次登入是透過伺服器01執行的,那麼這次的登入session資訊就存放到了記憶體01中;但是當我再次造訪時卻是伺服器02執行操作,而登入session資訊卻在記憶體01中,伺服器02無法獲取,所以它就會判斷我沒有登錄,回傳錯誤的資訊…
我們想要實現的就是透過一台伺服器登入所產生的session可以和其他伺服器共用,那麼該如何實現?
解決方法 想法就是既然這幾個伺服器自己的記憶體不能共享,那麼只要有一個共享空間供這幾個伺服器共同存取不就可以了(如圖);
首先想到的應該是資料庫,只要這些伺服器叢集共用一個資料庫,並且把產生的session資訊存放到資料庫中不就可以了,這樣大家都可以存取;資料庫有關聯式和非關係型(NoSql):
關係型資料庫:Mysql等
非關係型資料庫:Redis(K /V資料庫)等
這裡其實選擇非關係型資料庫最好,因為Redis基於內存,讀寫效能高,很適合這種使用者資訊頻繁讀取的情況;
還可以透過檔案伺服器實現,這裡就不介紹了;
還有一種方法,可以透過nginx的iphash實現,非常簡單,但是思路和上面兩種不同,原理就是同一個ip的所有請求都會被nginx進行iphash進行計算,將結果綁定到指定伺服器,之後這個請求都會被存取到該伺服器。
但是這樣就有一些問題,首先就算負載平衡就沒有太大意義了,如果綁定的伺服器掛了,那麼iphash也就失效了;又或者你的請求被其他服務分發而未走nginx服務,那麼iphash同樣不生效;所以謹慎使用;
下面我就簡單透過程式碼模擬一下如何透過redis配置輕鬆實現session共享
這裡有一個使用者管理項目,登入邏輯代碼會記錄下來登入使用者的session資訊:
然後同時開啟了該項目的兩個服務:localhost:8080和localhost :8082(可以當作兩台不同伺服器上執行的專案)
#開啟服務後可以存取對應的介面文件:
#-------------------------------------------------分割線-------- -----------------------------------
該服務都有以下兩個介面:(以下測試是在同一個服務中測試的)
登入介面:記錄登入使用者session資訊
登入測試:
取得目前使用者資訊介面:透過登入session取得目前使用者資訊
取得目前登入用戶資訊測試:
因為現在這是兩個服務,所以肯定實作不了共享session的,就算在8080埠的服務登入了,也無法在8082埠的服務取得到目前使用者資訊;(再次強調:上面測試可以取得到目前使用者資訊是因為在同一個服務中測試的,同一個服務session存放到他自己的記憶體當然可以自己存取了)
下面就透過redis配置實現共享session:
首先要下載redis,下載網路上找教學;這裡我直接用的在伺服器上透過docker建立的redis容器(簡單好用,強烈建議):
透過視覺化工具可以連接一下:
這樣redis就配置好了,下面在專案程式碼中配置redis:
在專案中引入redis依賴和spring-session設定依賴(自動將session 儲存到redis 中):
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.6.4</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.session/spring-session-data-redis --> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> <version>2.6.3</version> </dependency>
在application.yml檔案中設定連接redis和session相關設定:
spring: # session配置 session: timeout: 86400 # 设置session失效时间 store-type: redis # 修改spring-session存储配置,默认存储到服务器内存中,现在设置存到redis中(关键) # redis配置 redis: port: 8081 # redis的端口号(这里是我的redis容器在docker中对应的端口号) host: xx.xxx.xxx.xxx # 我的云服务器ip database: 0 # 设置存入redis的哪一个库(默认是0)
其實關鍵設定就一個: store-type: redis,只要配置了這個,那麼程式碼中session就會存放到redis中而不是自己的記憶體中;
接下來就可以測試了:
呼叫登入接口,生成用戶session信息,查看redis:
可以看到用戶登錄session已經存放到redis中了,這樣我在8080端口登錄,在8082也可以獲得登入的session資訊:
登入:
取得資訊:
這樣就透過redis實作session共享了;
需要注意:引入redis和spring-redis依賴版本需要接近。
以上是redis實作session共享的方法是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!