分布式下的session问题

在分布式项目中,session同步成为一大挑战。传统的session存储在单个服务器,无法满足多服务器间的状态共享。为解决此问题,可以将session存入公共存储如数据库或NoSql的redis。Spring Session框架提供了解决方案,简化了操作,通过配置可以使session数据存储在redis中,通过过滤器和装饰器模式实现session在分布式环境中的有效管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分布式下的session

在分布式项目下

session是一种会话状态,是储存在服务器上的,可以区分每个用户。浏览器会保存着对应的信息。浏览器保存的叫cookie。用户访问,浏览器会带上cookie让服务器识别。

如果是单体项目,session是在一个服务器下,所有的用户信息都保存在一个服务器,好做区分。

但是如果在分布式情况下,一个大的系统有很多模块,比如电商项目,有登录权限模块,商品模块,商品检索模块… 每个模块都是在不同的服务器上部署的,如果用户进行登录,session只在一个服务器上保存,其它服务器并不能同步。

痛点:解决session共享的问题。

这里就可以把session存储到一个公用的地方,各个模块都能取到的地方。如数据库, NoSql redis… 等。

spring session框架正好能解决这个问题,更加简化我们的操作。

项目中使用

可以照着官网来。

pom.xml

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <!-- https://docs.spring.io/spring-session/docs/2.2.2.RELEASE/reference/html5/guides/boot-redis.html -->
        <!-- 使用redis管理session -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;

/**
 * @author echo lovely
 * @date 2021/9/26 17:35
 * @description session 配置
 */

@EnableRedisHttpSession
@Configuration
public class HttpSessionConfig {

	// cookie 存储规则 确保在*.domain.com 同一个域名下及子域名
    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();
        serializer.setCookieName("JSESSIONID");
        // 设置子域共享session
        serializer.setDomainName("yourdomain.com");
        return serializer;
    }

    // RedisSerializer
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        // 使用json方式序列化.. 保存用户的session信息
        return new GenericJackson2JsonRedisSerializer();
    }


}

yaml配置, 配置session以redis存储

spring:
  redis:
    host: 192.168.56.10
    port: 6379
  session:
    store-type: redis
    timeout: 30m

springmvc使用的话,还是使用HttpSession, 设置值就行了。
这个httpSession会经过过滤器,过滤将请求和响应用装饰器模式包装。

原理

public class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper {

	// 原生request
	public SessionRepositoryRequestWrapper(HttpServletRequest original) {
		super(original);
	}

	public HttpSession getSession() {
		return getSession(true);
	}

	public HttpSession getSession(boolean createNew) {
		// create an HttpSession implementation from Spring Session
	}

	// ... other methods delegate to the original HttpServletRequest ...
}

经过过滤器后被包装。

public class SessionRepositoryFilter implements Filter {

	public doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		SessionRepositoryRequestWrapper customRequest =
			new SessionRepositoryRequestWrapper(httpRequest);

		chain.doFilter(customRequest, response, chain);
	}

	// ...
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值