spring-session+nginx實(shí)現(xiàn)session共享和負(fù)載均衡

一、為什么需要session共享

HttpSession是由servelet容器進(jìn)行管理的。而我們常用的應(yīng)用容器有 Tomcat/Jetty等, 這些容器的HttpSession都是存放在對(duì)應(yīng)的應(yīng)用容器的內(nèi)存中,在分布式集群的環(huán)境下,通常我們使用Nginx或者LVS、Zuul等進(jìn)行反向代理和負(fù)載均衡,因此用戶(hù)請(qǐng)求是由一組提供相同服務(wù)的應(yīng)用來(lái)進(jìn)行處理,而用戶(hù)最終請(qǐng)求到的服務(wù)由Nginx和LVS、Zuul進(jìn)行確定。
那么問(wèn)題就來(lái)了,我們?cè)鯓颖WC多個(gè)相同的應(yīng)用共享同一份session數(shù)據(jù)?對(duì)于這種問(wèn)題Spring為我們提供了Spring Session進(jìn)行管理我們的HttpSession。

二、基礎(chǔ)Spring Boot配置Spring Session

1.添加Spring session的包,而Spring session 是將HttpSession存放在Redis中,因此需要添加Redis的包。我們這里是用了Spring boot進(jìn)行配置Redis。
<dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session</artifactId>
                <version>1.3.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-redis</artifactId>
            <version>1.3.5.RELEASE</version>
        </dependency>
        <dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session-data-redis</artifactId>
                <version>1.2.2.RELEASE</version>
                <type>pom</type>
        </dependency>
2、啟動(dòng)類(lèi)使用@EnableRedisHttpSession注解進(jìn)行配置啟用使用Spring session
@SpringBootApplication
@MapperScan(basePackages = "com.engine56.container.common.mapper")
@EnableTransactionManagement
public class ContainerApplication {
    
    public static void main( String[] args ){
        new SpringApplicationBuilder(ContainerApplication.class).web(true).run(args);
    }
3、配置我們的Redis鏈接,我們這里使用的是Spring Boot作為基礎(chǔ)進(jìn)行配置,因此我們只需要在YML或者Properties配置文件添加Redis的配置即可。此處在application.properties中配置
spring.redis.database=0
# Redis服務(wù)器地址
spring.redis.host=127.0.0.1
# Redis服務(wù)器連接端口
spring.redis.port=6379
# Redis服務(wù)器連接密碼(默認(rèn)為空)
spring.redis.password=123456
# 連接池最大連接數(shù)(使用負(fù)值表示沒(méi)有限制)
spring.redis.pool.max-active=8
# 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒(méi)有限制)
spring.redis.pool.max-wait=-1
# 連接池中的最大空閑連接
spring.redis.pool.max-idle=8
# 連接池中的最小空閑連接
spring.redis.pool.min-idle=0
# 連接超時(shí)時(shí)間(毫秒)
spring.redis.timeout=0
4、在controller編寫(xiě)代碼
@GetMapping("/session")
    public String test(HttpServletRequest request){
        HttpSession session = request.getSession();  
        UUID uid = (UUID) session.getAttribute("uid");
        String msg = "拿到了session!";
        if (uid == null) {  
            uid = UUID.randomUUID();  
            session.setAttribute("uid", uid);
            session.setAttribute("userinfo","張三,男,12歲");
            msg="沒(méi)拿到session";
        }else{
            return msg+" :::  "+session.getAttribute("userinfo");
        }
        return msg;
    }
5、測(cè)試

將項(xiàng)目用兩個(gè)不同端口啟動(dòng),用第一個(gè)端口訪問(wèn)后,用第二個(gè)端口再訪問(wèn),看是否拿到session。
測(cè)試結(jié)果:第一次訪問(wèn)輸出:沒(méi)拿到session;第二次訪問(wèn)輸出:拿到了session!張三,男,12歲。

三、SpringSession與shiro集成

1、首先要了解springSession實(shí)現(xiàn)原理
  • 通過(guò)@EnableRedisHttpSession可以知道,Spring Session是通過(guò)RedisHttpSessionConfiguration類(lèi)進(jìn)行配置,該類(lèi)是用于創(chuàng)建一個(gè)過(guò)濾SessionRepositoryFilter
    擴(kuò)展知識(shí):Spring Session提供了3種方式存儲(chǔ)session的方式。
    @EnableRedisHttpSession-存放在緩存redis
    @EnableMongoHttpSession-存放在Nosql的MongoDB
    @EnableJdbcHttpSession-存放數(shù)據(jù)庫(kù)
  • 此filter放在所有filter之前,接管session管理。
  • 如何獲取getSession:
    先檢查是不是已經(jīng)有session了。如果有的話,就將其返回,
    否則的話,它會(huì)檢查當(dāng)前的請(qǐng)求中是否有session id。
    如果有的話,將會(huì)根據(jù)這個(gè)session id,從它的SessionRepository中加載session。
    如果session repository中沒(méi)有session,或者在當(dāng)前請(qǐng)求中,沒(méi)有當(dāng)前
    session id與請(qǐng)求關(guān)聯(lián)的話,那么它會(huì)創(chuàng)建一個(gè)新的session,并將其
    持久化到session repository中
  • 如何存儲(chǔ)session
    請(qǐng)求時(shí),先獲取當(dāng)前session,不為空時(shí)即保存session。保存后,判斷
    當(dāng)前請(qǐng)求中的sessionId是否與當(dāng)前sessionId一致,若不一致,則將當(dāng)
    前sessionId保存至cookie。
2、shiro配置
@Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(EgRealm myShiroRealm) {
        DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
        dwsm.setRealm(myShiroRealm);
        //<!-- 用戶(hù)授權(quán)/認(rèn)證信息Cache, 采用EhCache 緩存 --> 
        dwsm.setCacheManager(getEhCacheManager());
        return dwsm;
    }

ServletContainerSessionManager:DefaultWebSecurityManager使用的默認(rèn)實(shí)現(xiàn),用于Web環(huán)境,其直接使用Servlet 容器的會(huì)話;
故,不需要再額外配置,spring-session直接為shiro所用。

三、nginx實(shí)現(xiàn)負(fù)載均衡

以上實(shí)現(xiàn)了session共享后,如何做到負(fù)載均衡就要靠nginx了,配置如下:
(具體需要如何配置看項(xiàng)目業(yè)務(wù)需要了)

upstream blank {
        server 127.0.0.1:3000 weight=10;
        server 127.0.0.1:3001 weight=1;
    }

    server {
        listen       8000;
        server_name  localhost; 
    location ~^/engine56{
        proxy_pass  http://blank;//注意:blank要和上面upstream后的名稱(chēng)一致。
        }
        location / {
            root  D:\xxxx\xxxxx;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容