1. Sesssion共享解决方案:
1.1 使用nginx或者haproxy
使用Nginx的ipip_hash配置
使用haproxy可以用 balance source配置
从而使同一个ip的请求发到同一台服务器,但这样就不再支持负载均衡了
1.2 利用数据库同步session(效率不高)
1.3 利用cookie同步session数据原理图如下
缺点:安全性差、http请求都需要带参数增加了带宽消耗
1.4 使用tomcat内置的session同步(同步可能会产生延迟)
1.5 使用token代替session
1.6 使用spring-session+redis
运用spring-session集成好的方案, 将值存储在redis中,下面本文将重点介绍该方案。
2. 代码编写
创建一个Spring Boot Web项目,添加Redis和Session共享倚赖,如下:
<!--spring boot 与redis应用基本环境配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring session 与redis应用基本环境配置,需要开启redis后才可以使用,不然启动Spring boot会报错 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
其中Spring Session可以透明化的替换掉应用的Session,Redis的基本配如下:
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
#spring.redis.password=123@456
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.max-wait=-1ms
spring.redis.jedis.pool.min-idle=0
server.port=${PORT:8080}
创建一个Controller用于测试
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
@RestController
public class HelloController {
//注入项目的端口号,用于区分是哪个服务器提供的服务
@Value("${server.port}")
String port;
//向Session中存储数据
@PostMapping("/save")
public String saveName(String name, HttpSession session) {
session.setAttribute("name", name);
return port;
}
//从session获取数据
@GetMapping("/get")
public String getName(HttpSession session) {
return port + ":"
+ session.getAttribute("name").toString();
}
}
还有最关键的一部,添加注解@EnableRedisHttpSession(),该注解原理参考
@SpringBootApplication
@EnableRedisHttpSession()
public class SessionApplication {
public static void main(String[] args) {
SpringApplication.run(SessionApplication.class, args);
}
}
最后通过设置端口分别启动为 8080 和8081 两台服务。
3. Nginx负载均衡
如果要在linux下搭建nginx可以参考:Nginx在Linux下的安装(详细)
修改配置文件
vim /usr/local/nginx/conf/nginx.conf
upstream session{
server 127.0.0.1:8080 weight=1;
server 127.0.0.1:8081 weight=1;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://session;
proxy_redirect default;
}
}
上面只列出了需要修改和添加的配置,先配置了两个上游服务器,即两个real server ,两个server的权重都是一,意味着请求将进行平均分配,然后在server中配置拦截规则,将请求转发到定义好的real server上
重启Nginx
/usr/local/nginx/sbin/nginx -s reload
4. 测试
启动好nginx和realServer后 访问 http://localhost/save?name=mingrun
可以看到返回值为8081,表示在8081服务器上存储了session
调用get接口,可以发现 8081 和 8080 都能返回存储的值
session共享完成。