springboot项目Nginx+Tomcat实现负载均衡结合Redis实现session共享问题

对于分布式使用Nginx+Tomcat实现负载均衡,当同一个用户登入后,再次访问可能分发到不同的服务,这样我们就取不到之前登入session,出现未登入现象。所以我们必须解决共享session问题。

 方式一:存储在数据库中 , 用户登入时,把session信息储存在数据库中,然后再需要获取session的地方进行读取。

 方式二 :cookie 共享session ;当用户登入时,把 cookie储存在客户端,当用户需要session判断是否登入时,首先判断本服务器是否有session,如果没有同步cookie信息。(购物车在数据库和cookie都存,就是为了把用户未登入时产生的购物车同步到登入用户上)

   方式三:  服务器共享session ,使用一台作为用户的登录服务器,当用户登录成功之后,会将session写到当前服务器上,我们通过脚本或者守护进程将session同步到其他服务器上,这时当用户跳转到其他服务器,session一致,也就不用再次登录。
 

方式四  :通过缓存同步session,用户登入时,把登入信息放在redis或者memcache中,我们取session信息的时候都从缓存中取。(重写session创建 获取 销毁 方法 创建存缓存中  获取从缓存中获取  销毁缓存中记录和服务器记录)

本文大致分两步:

1.springboot中如何使用redis。
2.redis如何解决session共享

pom依赖 

<!--redis配置开始-->
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-redis</artifactId>
</dependency>
<dependency>
 <groupId>org.springframework.data</groupId>
 <artifactId>spring-data-redis</artifactId>
 <version>${spring-data-redis.version}</version>
</dependency>
<dependency>
 <groupId>redis.clients</groupId>
 <artifactId>jedis</artifactId>
 <version>${jedis.version}</version>
</dependency>
<dependency>
 <groupId>org.springframework.session</groupId>
 <artifactId>spring-session-data-redis</artifactId>
</dependency>
<!--redis配置结束-->

添加redis配置类

该配置类同样可以配置缓存失效时间等。

package com.mos.quote.config;
 
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
 
/**
 * @author Administrator
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
  @Bean
  public KeyGenerator KeyGenerator(){
    return (target, method, params) -> {
      StringBuilder sb = new StringBuilder();
      sb.append(target.getClass().getName());
      sb.append(method.getName());
      for (Object obj : params) {
        sb.append(obj.toString());
      }
      return sb.toString();
    };
  }
 
  @Bean
  public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
    StringRedisTemplate template = new StringRedisTemplate(factory);
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    ObjectMapper om = new ObjectMapper();
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jackson2JsonRedisSerializer.setObjectMapper(om);
    template.setValueSerializer(jackson2JsonRedisSerializer);
    template.afterPropertiesSet();
    return template;
  }
 
  @Bean
  public CacheManager cacheManager(RedisTemplate<String,String> redisTemplate) {
    RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
    //设置缓存过期时间
    rcm.setDefaultExpiration(600000);
    return rcm;
  }
}

在application.propreties中配置redis

# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=192.168.1.118
# Redis服务器连接端口
spring.redis.port=6381
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0

单元测试

1、set值(字符串)

@Test

public void put(){

  stringRedisTemplate.opsForValue().set("test001","test001");

  Assert.assertEquals("test001", stringRedisTemplate.opsForValue().get("test001"));

}

往redis放一个key为test001、value为test001的值,然后查看redis

2、set值(object)

@Test
 public void testObj() throws Exception {
   SysUser user=new SysUser();
   user.setId("123456");
   user.setName("张三");
   ValueOperations<String, SysUser> operations=redisTemplate.opsForValue();
   operations.set("user1", user);
   operations.set("user2", user,5, TimeUnit.SECONDS);
   Thread.sleep(6000);
   Assert.assertFalse(redisTemplate.hasKey("user2"));
 }

往redis分别放key为user1和user2的对象,user2设置5秒失效,线程等待6秒再完成,期望结果:redis中有user1,没有user2,bingo!!!

解决session共享

使用spring-session-data-redis实现session共享,pom中引入该依赖(上文已添加),添加SessionConfig配置类。
对,没看错,只需要这个就够了。最长有效时间根据自己情况随意配置即可。

package com.mos.quote.config;
 
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
 
/**
 * @author Administrator
 */
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3000)
public class SessionConfig {
}

测试

写一个简单Controller,如下

@RequestMapping("testSessionTimeOut")
  public String testSessionTimeOut(String id,HttpSession session,Model model){
    Area area = areaService.getById(id);
    System.out.println("sessionId-------->"+session.getId());
    model.addAttribute("area",JSON.toJSONString(area));
    session.setAttribute("area",JSON.toJSONString(area));
    return "demo/test1";
  }

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值