1、项目中使用到了session,当做了分布式集群之后需要处理的问题?
需要处理分布式Session问题。
2、问题场景:
项目中使用到了session,在后期的时候使用Nginx做了负载均衡处理高并发的问题,那么这个使用就可能会出现,前面请求道的那台服务器是存值进入session,后面请求分配到的服务器是取session里面的值,这个时候就会出现session里面的值取不出来,报异常的问题
测试代码:
package com.junlaninfo.base.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import lombok.extern.slf4j.Slf4j;
/**
* @author 作者 xuexionghui:
@emil:41366915@qq.com
* @version 创建时间:2019年1月28日 下午10:43:38
* 类说明 演示session分布式问题
* 加上Nginx 演示分布式问题
*/
@RestController
@Slf4j
public class TestSessionController {
@Value("${server.port}")
private String serverPort;
// 创建session 会话
@RequestMapping("/createSession")
public String createSession(HttpServletRequest request, String nameValue) {
HttpSession session = request.getSession();
log.info(">>>>>>>存入Session,SessionId:{},SessionValue:{}", session.getId(), nameValue);
session.setAttribute("name", nameValue);
return "success" + ",端口号:" + serverPort;
}
// 获取session 会话
@RequestMapping("/getSession")
public Object getSession(HttpServletRequest request) {
HttpSession session = request.getSession(false);
log.info(">>>>>>>获取Session sessionid:{}", session.getId());
Object value = session.getAttribute("name");
return value + ",端口号:" + serverPort;
}
}
使用Nginx做负载均衡:
upstream backServer{
server 192.168.81.1:81;
server 192.168.81.1:82;
}
server {
listen 80;
server_name shop.mayikt.com;
location / {
proxy_pass http://backServer;
index index.html index.htm;
}
}
3、解决办法:
a、使用token代替session
b、使用spring-session解决分布式session问题
(1)添加依赖:
<!--spring session 与redis应用基本环境配置,需要开启redis后才可以使用,不然启动Spring boot会报错 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
(2)进行redis的配置
(3)建类写配置文件
//这个类用配置redis服务器的连接
//maxInactiveIntervalInSeconds为SpringSession的过期时间(单位:秒)
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SessionConfig {
// 冒号后的值为没有配置文件时,制动装载的默认值
@Value("${redis.hostname:localhost}")
String hostName;
@Value("${redis.port:6379}")
int port;
@Value("${redis.password:123456}")
String passWord;
@Bean
public JedisConnectionFactory connectionFactory() {
JedisConnectionFactory connection = new JedisConnectionFactory();
connection.setPort(port);
connection.setHostName(hostName);
connection.setPassword(passWord);
return connection;
}
}