【冲刺大厂P6专题】集群分布式Session是如何实现的

目录

分布式环境下session会存在的问题?

分布式Session⼀致性的⽅案

一.Nginx的 IP_Hash 策略(可以使⽤)

二.Session复制(不推荐)

三.Session共享,Session集中存储(推荐)


分布式环境下session会存在的问题?

图解:

文字解:

出现这个问题的原因从根本上来说是因为Http协议是⽆状态的协议。客户端和服务端在某次会话中产⽣的数据不会被保留下来,所以第⼆次请求服务端⽆法认识到你曾经来过, Http为什么要设计为⽆状态协议?早期都是静态⻚⾯⽆所谓有⽆状态,后来有动态的内容更丰富,就需要有状态,出现了两种⽤于保持Http状态的技术,那就是Cookie和Session。⽽出现上述不停让登录的问题,第一访问到tomcat1,登录成功sesssion中保持登录信息,

例如刷新页面nginx轮询到tomcat2,然而tomcat2并没有tomcat1的session,所以重定向到登录页面重新登录。

分布式Session⼀致性的⽅案

一.Nginx的 IP_Hash 策略(可以使⽤)

同⼀个客户端IP的请求都会被路由到同⼀个⽬标服务器,也叫做会话粘滞。

优点:

     配置简单,不⼊侵应⽤,不需要额外修改代码。

缺点:

 1.服务器重启Session丢失

 2.存在单点负载⾼的⻛险

 3.单点故障问题

二.Session复制(不推荐)

   多个tomcat之间通过修改配置⽂件,达到Session之间的复制

 优点:

  1.不⼊侵应⽤

  2.便于服务器⽔平扩展

  3.能适应各种负载均衡策略

  4.服务器重启或者宕机不会造成Session丢失

 缺点:

   1.性能低

   2.内存消耗

   3.不能存储太多数据,否则数据越多越影响性能

   4.延迟性

三.Session共享,Session集中存储(推荐)

  图解:

     

 

 

优点:

1.能适应各种负载均衡策略

2.服务器重启或者宕机不会造成Session丢失

3.扩展能⼒强

4.适合⼤集群数量使⽤

缺点:

1.对应⽤有⼊侵,引⼊了和Redis的交互代码

Spring Session使得基于Redis的Session共享应⽤起来⾮常之简单

使用步骤:

 1.导入maven坐标

  

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-redis</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.session</groupId>

<artifactId>spring-session-data-redis</artifactId>

</dependency>

2.配置redis(以自己的ip为主)

spring.redis.database=0

spring.redis.host=127.0.0.1

spring.redis.port=6379

3.在SpringBoot启动类型添加注解@EnableRedisHttpSession

package com.yang;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.boot.builder.SpringApplicationBuilder;

import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

import org.springframework.cache.annotation.EnableCaching;

import org.springframework.context.annotation.Bean;

import org.springframework.session.data.redis.config.ConfigureRedisAction;

import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@SpringBootApplication

@EnableCaching

@EnableRedisHttpSession

public class LoginApplication  extends SpringBootServletInitializer {

    @Override

    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {

        return builder.sources(LoginApplication.class);

    }

    public static void main(String[] args) {

        SpringApplication.run(LoginApplication.class, args);

    }

    @Bean

    public static ConfigureRedisAction configureRedisAction() {

        return ConfigureRedisAction.NO_OP;

    }

}

4.使用案例

/**

 * 请求权限验证

 */

public class RequestInterceptor implements HandlerInterceptor {

    /**

     * 之前执行(进入Handler处理之前)

     * 可以进行权限验证

     * @param request

     * @param response

     * @param handler

     * @return  true放行,false中止程序

     * @throws Exception

     */

    @Override

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        HttpSession session = request.getSession();

        System.out.println("==========>>>>sessionId:" + session.getId());

        System.out.println("======SESSION::::" + session);

        Enumeration<String> attrs = session.getAttributeNames();

// 遍历attrs中的

        while(attrs.hasMoreElements()){

// 获取session键值

            String name = attrs.nextElement().toString();

            // 根据键值取session中的值

            Object vakue = session.getAttribute(name);

            // 打印结果

            System.out.println("------" + name + ":" + vakue +"--------\n");

        }

        System.out.println("===============>>>>>>当前uri:" + request.getRequestURI());

        Object username = session.getAttribute("username");

        System.out.println("=================>>>>>username:" + username);

        if(username == null) {

            // 没有登录,重定向到登录页

            System.out.println("未登录,请登录");

            response.sendRedirect(request.getContextPath() + "/login/toLogin");

            return false;

        }else{

            System.out.println("已登录,放行请求");

            // 已登录,放行

            return true;

        }

    }

    /**

     * 之中执行(Handler处理完毕但尚未跳转页面)

     * @param request

     * @param response

     * @param handler

     * @param modelAndView

     * @throws Exception

     */

    @Override

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    /**

     * 之后执行(Handler处理完毕而且已经跳转页面)

     * @param request

     * @param response

     * @param handler

     * @param ex

     * @throws Exception

     */

    @Override

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值