一、简介
HttpSession是通过Servlet容器进行创建和管理的,在单机环境中创建的Session信息是存储在Web服务器内存中,现在很多的服务器都采用分布式集群的方式进行部署,一个Web应用,可能部署在几台不同的服务器上,通过LVS或者Nginx等进行负载均衡(一般使用Nginx+Tomcat实现负载均衡)。此时来自同一用户的Http请求将有可能被分发到不同的web站点中去(如:第一次分配到A站点,第二次可能分配到B站点)。
可以在所有分布式节点前增加一个中间层把不同服务器上的Session 放在该中间层中。计算机领域无不体现层级结构的设计思想,让我想起一句经典“计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决”
二、流程
spring boot 对Session 共享提供了非常便捷的集成,spring boot 使用 redis 作为中间层实现Session 共享。
1.新建Web 项目,pom.xml 添加如下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
2.配置application.yml
spring:
redis:
host: 192.168.243.133
3.TestController.java
package com.vincent.controller;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@Value("${server.port}")
private int port;
@GetMapping("/test/save")
public Object save(HttpSession session) {
Object date = session.getAttribute("date");
if(date == null) {
date = new Date();
session.setAttribute("date",date);
}
return date;
}
@GetMapping("/test/get")
public Object get(HttpSession session,HttpServletRequest request) {
Map<String, Object> rst = new HashMap<>();
rst.put("date", session.getAttribute("date"));
rst.put("server_port", port);
return rst;
}
}
4.运行项目分别使用8080 / 8081 端口
6.配置nginx 负载均衡 /usr/local/nginx/conf/nginx.conf
upstream test.vincent.com {
server 192.168.243.1:8080 weight=1;
server 192.168.243.1:8081 weight=1;
}
server {
listen 9000;
server_name "test-server";
location / {
proxy_pass http://test.vincent.com;
#proxy_redirect default;
}
}
upstream 配置节点必须在http内,server 外,否则会有错误
upstream 配置上游服务器,并配置服务节点
server 配置服务器监听的端口、名称、转发
三、测试
1.访问 http://192.168.243.133:9000/test/save 保存数据到Session
2.访问 http://192.168.243.133:9000/test/get
再次刷新接口
nginx 会对请求转发到配置的服务器上。upstream 中服务节点可根据实际服务器性能配置相关权重。
四、总结
1.application.yml 配置
server:
servlet:
session:
cookie:
max-age: ...
可实现Session 有效期管理控制
2.nginx 配置文件的上游服务器可配置备份服务器,其中的服务器宕机后Nginx 将会启用备用服务器
修改 nginx.conf upstream 如下:
upstream test.vincent.com {
server 192.168.243.1:8080 weight=1;
server 192.168.243.1:8081 weight=1 backup;
}
nginx -s reload 命令使nginx 配置生效
访问 http://192.168.243.133:9000/test/get
刷新该请求输出的也是8080 端口,说明8081 端口的服务器配置为备份服务器成功,关闭 8080 端口的Web 进程并刷新该接口
成功输出8081 端口,说明nginx 负载均衡/备份服务 配置成功。
重启8080端口服务后,刷新 http://192.168.243.133:9000/test/get 访问的是 8080 端口的应用。
8081 端口的服务将进入备份状态,在8080端口服务停止后8081 端口服务才会启用。