在使用spring boot做负载均衡的时候,多个app之间的session要保持一致,这样负载到不同的app时候,在一个app登录之后,而访问到另外一台服务器的时候,session丢失。

springboot的session存储在mongo中 springboot保存session_spring


nginx.conf配置示例

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

	upstream spring-session {
		server 127.0.0.1:8081; 
		server 127.0.0.1:8082; 
		server 127.0.0.1:8083;
	}
    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass http://spring-session;
			proxy_set_header Host $host; 
			proxy_set_header X-Real-IP $remote_addr; 
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        }
    }
}

请求本地localhost,可调用8081,8082,8083三个端口的应用

常规的解决方案都是使用:如apache使用mod_jk.conf,使用Memcached进行共享。

       在开发spring boot app的时候可以借助 spring session 和redis或者ehcache,用外置的redis或者ehcache来存储session的状态,这里使用redis进行介绍,ehcache实现是一样的。

增加相关依赖

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

 

       在spring boot的文档中,告诉我们添加@EnableRedisHttpSession来开启spring session支持,而@EnableRedisHttpSession这个注解是由spring-session-data-redis提供的,所以在pom.xml文件中spring-session-data-redis

 

 

RedisSessionConfig.java

package com.wisely.base;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@Configuration
@EnableRedisHttpSession
public classRedisSessionConfig {
}

 

如果需要添加失效时间可以使用以下的写法:

@EnableRedisHttpSession(maxInactiveIntervalInSeconds= 60) //1分钟失效


@EnableRedisHttpSession注解的源码如下,可以看到可以配置三个参数:

  • maxInactiveIntervalInSeconds :session中的数据的过期时间(不是session在redis中的过期时间)
  • redisNamespace :命名空间,可以配置当前应用的名称,我这里配置了 mysession.
  • redisFlushMode :redis保存session的方式,默认 ON_SAVE 
    有两种方式: IMMEDIATE:一旦创建session的时候就立即保存. ON_SAVE:创建session的时候不会保存,但当往session中添加数据的时候就会保存


相关配置修改

在application.properties修改redis配置信息(请自行安装redis),请根据实际修改。如:

######   Redis config start ######
spring.redis.database=0
spring.redis.host=192.168.41.60
spring.redis.port=6379
spring.redis.password=
spring.redis.pool.max-active=20
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.timeout=0
######   Redis config end ######

在application.properties还需指定分布式数据存放的方式为redis。如:(当然spring-session 也支持更多的存储方式,具体参考文档)

spring.session.store-type=redis

所有实体类实现Serializable接口

public class SysResource implements Serializable

 

查看效果

这时候登录系统在不同的app之间跳转的时候,session都是一致了,redis上可以看到:

总结

使用这些代码之后 ,无论你使用nginx或者apache,都无须在关心多个app之间的session一致的问题了。

 

注意事项

(1)redis版本号需要是2.8以上否则会抛异常:ERR Unsupported CONFIG parameter: notify-keyspace-events;

 

(2)RedisSessionConfig需要放在App.java启动类可以扫描的位置;

配置Nginx的时候,注意要注释ip_hash,不然通一个IP的请求,会被转发到通一个服务里面。

 

upstream spring-session {
    # ip_hash
	server 127.0.0.1:8081; 
	server 127.0.0.1:8082; 
	server 127.0.0.1:8083;
}



补充------------

如果使用Security,下面的几步需要配置。

 

Spring Security 配置

在项目中添加该类:


[java]  view plain  copy



1. public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {  
2.   
3. public SecurityInitializer() {  
4. super(SecurityConfig.class, Config.class);  
5.         }  
6. }

super()的第二个参数,就是我们上面的那个Config文件。添加这个配置文件后,Spring Security就会把Session放到Redis中,这样基于Spring Security的项目也可以实现Session共享了。

Initializer 配置

这一步写法异常简单,还是创建文件:


[java]  view plain  copy



1. public class Initializer extends AbstractHttpSessionApplicationInitializer {  
2.   
3. }

就这样,继承一个类即可。