一、概述

1.1 什么是Session

  Session 是客户端与服务器通讯会话技术, 比如浏览器登陆、记录整个浏览会话信息 

1.2 Session实现原理

  客户对向服务器端发送请求后,Session 创建在服务器端,返回Sessionid给客户端浏览器保存在本地,当下次发送请求的时候,在请求头中传递sessionId获取对应的从服务器上获取对应的Sesison

1.3 Session常见问题

Session 保证在那里?

  答案:存放在服务器上
  

关闭浏览器Session会失效吗

  答案:不会消失
  

服务器集群之后,Session产生的问题

  
  如果服务器产生了集群后,因为session是存放在服务器上,客户端会使用同一个Sessionid在多个不同的服务器上获取对应的Session,从而会导致Session不一致问题。
  

1.4 Nginx

Nginx配置负载均衡

Nginx负载均衡提供上游服务器(真实业务逻辑访问的服务器),负载均衡、故障转移、失败重试、容错、健康检查等。
当上游服务器(真实业务逻辑访问的服务器)发生故障时,可以转移到其他上游服务器(真实业务逻辑访问的服务器)。

Upstream Server配置

upstream 主要配置如下:
IP地址和端口号:配置上游服务器的IP地址和端口
###定义上游服务器(需要被nginx真实代理访问的服务器) 默认是轮训机制
upstream backServer{
server 127.0.0.1:8080;
server 127.0.0.1:8081;
} server {
listen 80;
server_name www.itmayiedu.com;
location / {
### 指定上游服务器负载均衡服务器
proxy_pass http://backServer;
index index.html index.htm;
}
}

负载均衡算法

  • 1、轮询(默认),每个请求按时间顺序逐一分配到不同的后端服务,如果后端某台服务器死机,自动剔除故障系统,使用户访问不受影响。
  • 2、weight(轮询权值),weight的值越大分配到的访问概率越高,主要用于后端每台服务器性能不均衡的情况下。或者仅仅为在主从的情况下设置不同的权值,达到合理有效的地利用主机资源。
    • 3、ip_hash,每个请求按访问IP的哈希结果分配,使来自同一个IP的访客固定访问一台后端服务器,并且可以有效解决动态网页存在的session共享问题。俗称IP绑定。
    • 4、fair(第三方),比 weight、ip_hash更加智能的负载均衡算法,fair算法可以根据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间 来分配请求,响应时间短的优先分配。Nginx本身不支持fair,如果需要这种调度算法,则必须安装upstream_fair模块。
    • 5、url_hash(第三方),按访问的URL的哈希结果来分配请求,使每个URL定向到一台后端服务器,可以进一步提高后端缓存服务器的效率。Nginx本身不支持url_hash,如果需要这种调度算法,则必须安装Nginx的hash软件包。

二、Session 相关代码演示

2.1 Controller

 @SpringBootApplication
@RestController
public class TestSessionController { // 创建session 会话
@RequestMapping("/createSession")
public String createSession(HttpServletRequest request, String nameValue) {
HttpSession session = request.getSession();
System.out.println("存入Session sessionid:信息" + session.getId() + ",nameValue:" + nameValue);
session.setAttribute("name", nameValue);
return "success";
} // 获取session 会话
@RequestMapping("/getSession")
public Object getSession(HttpServletRequest request) {
HttpSession session = request.getSession();
System.out.println("获取Session sessionid:信息" + session.getId());
Object value = session.getAttribute("name");
return value;
} public static void main(String[] args) {
SpringApplication.run(TestSessionController.class, args);
}
}

2.2 TestSessionController

@SpringBootApplication
@RestController
public class TestSessionController {
@Value("${server.port}")
private String serverPort; @RequestMapping("/")
public String index() {
return serverPort;
} // 创建session 会话
@RequestMapping("/createSession")
public String createSession(HttpServletRequest request, String nameValue) {
HttpSession session = request.getSession();
System.out.println(
"存入Session sessionid:信息" + session.getId() + ",nameValue:" + nameValue + ",serverPort:" + serverPort);
session.setAttribute("name", nameValue);
return "success-" + serverPort;
} // 获取session 会话
@RequestMapping("/getSession")
public Object getSession(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) {
return serverPort + "-" + "没有找到对应的session值";
}
System.out.println("获取Session sessionid:信息" + session.getId() + "serverPort:" + serverPort);
Object value = session.getAttribute("name");
return serverPort + "-" + value;
} public static void main(String[] args) {
SpringApplication.run(TestSessionController.class, args);
}
}

三、分布式Session一致性解决方案

3.1 nginx或者haproxy实现IP绑定

  • 用Nginx 做的负载均衡可以添加ip_hash这个配置,用haproxy做的负载均衡可以用 balance source这个配置。从而使同一个ip的请求发到同一台服务器。

3.2 利用数据库同步session

3.3 使用Session集群存放Redis

  使用spring-session框架,底层实现原理是重写httpsession

引入maven依赖

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<weixin-java-mp.version>2.8.0</weixin-java-mp.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.locales>zh_CN</project.build.locales>
</properties> <dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- <exclusions> <exclusion> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> </exclusion> </exclusions> -->
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- Testing Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--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>
</dependencies>

YML配置信息

server:
port: 8080
redis:
hostname: 192.168.212.151
port: 6379
password: 123456
启动redis /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

创建SessionConfig

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; //这个类用配置redis服务器的连接
//maxInactiveIntervalInSeconds为SpringSession的过期时间(单位:秒)
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SessionConfig { // 冒号后的值为没有配置文件时,制动装载的默认值
@Value("${redis.hostname:localhost}")
String HostName;
@Value("${redis.port:6379}")
int Port; @Bean
public JedisConnectionFactory connectionFactory() {
JedisConnectionFactory connection = new JedisConnectionFactory();
connection.setPort(Port);
connection.setHostName(HostName);
return connection;
}
}

初始化Session

//初始化Session配置
public class SessionInitializer extends AbstractHttpSessionApplicationInitializer{
public SessionInitializer() {
super(SessionConfig.class);
}
}

3.4 最靠谱的分布式Session解决方案

基于令牌(Token)方式实现Session解决方案,因为Session本身就是分布式共享连接。

Service

@Service
public class TokenService {
@Autowired
private RedisService redisService; // 新增 返回token
public String put(Object object) {
String token = getToken();
redisService.setString(token, object);
return token;
} // 获取信息
public String get(String token) {
String reuslt = redisService.getString(token);
return reuslt;
} public String getToken() {
return UUID.randomUUID().toString();
} }

TokenController

@RestController
public class TokenController {
@Autowired
private TokenService tokenService;
@Value("${server.port}")
private String serverPort; @RequestMapping("/put")
public String put(String nameValue) {
String token = tokenService.put(nameValue);
return token + "-" + serverPort;
} @RequestMapping("/get")
public String get(String token) {
String value = tokenService.get(token);
return value + "-" + serverPort;
}
}

  

【Distributed】分布式Session一致性问题的更多相关文章

  1. 分布式session一致性问题

    1.分布式session一致性 :指服务器集群情况下session共享的问题. 2.session的作用:保存服务器(tomcat)与客户端(浏览器)整个通讯的会话基本信息. 3.session应用场 ...

  2. 分布式Session一致性解决方案有哪些?

    1.使用cookie代替session(不安全,不推荐使用) 2.使用数据库存储session(效率低,不推荐使用) 3.使用nginx反向代理ip绑定方法,同一个ip只能在同一台服务器上进行访问(不 ...

  3. 分布式session一致性

    实现思路:当客户端发送请求到服务端后,在后台生成一个token,将token作为key,用户状态信息作为value,存入redis缓存中,并设置过期时间,最后把token返回给客户端 客户端第会保存t ...

  4. 分布式Session共享解决方案

    分布式Session解决方案 Author:SimpleWu 分布式Session一致性? 说白了就是服务器集群Session共享的问题 Session的作用? Session 是客户端与服务器通讯会 ...

  5. 【Redis】分布式Session

    一.问题引出 1.1 Session的原理 1.2 问题概述 二.解决方案 三.代码实现-使用Token代替Session 3.1 Service 3.2 TokenController 一.问题引出 ...

  6. 搞懂分布式技术11:分布式session解决方案与一致性hash

    搞懂分布式技术11:分布式session解决方案与一致性hash session一致性架构设计实践 原创: 58沈剑 架构师之路 2017-05-18 一.缘起 什么是session? 服务器为每个用 ...

  7. Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session框架

    Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session import tornado.ioloop import tornado.web from myhas ...

  8. 分布式下Session一致性问题

    一.Session一致性问题 1.1 什么是Session 用户使用网站的服务,基本上需要浏览器和web服务器进行多次交互,web服务器如何知道哪些请求是来自哪个会话的? 具体方式为:在会话开始时,分 ...

  9. 分布式下Session一致性架构举例

    一.问题及方案 见这篇文章:分布式下Session一致性问题 二.分布式环境搭建: 系统环境 [root@centos7 ~]# cat /etc/redhat-release CentOS Linu ...

随机推荐

  1. 升级系统中的java到1.8版本

    (1).安装或升级java,并配置环境变量 注意:此处分为yum安装与rpm安装,区别在于yum安装省事但配置麻烦,rpm安装麻烦但配置省事. 1)yum安装 在安装前可以使用yum list ins ...

  2. JAVA 基础编程练习题36 【程序 36 移动位置】

    36 [程序 36 移动位置] 题目:有 n 个整数,使其前面各数顺序向后移 m 个位置,最后 m 个数变成最前面的 m 个数 package cskaoyan; public class cskao ...

  3. 【ARTS】01_27_左耳听风-201900513~201900519

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

  4. 联想拯救者电脑装Ubuntu没有WIFI

    最近给联想电脑装Ubuntu系统,但是装完之后总是无法启动WIFI,而宽带上网却可以,给出一个解决办法,但是该办法应该只适合联想电脑,其他电脑请自测! 打开终端,输入下面指令: sudo modpro ...

  5. 单例Bean注册表接口SingletonBeanRegistry

    Github: SingletonBeanRegistry.java SingletonBeanRegistry package org.springframework.beans.factory.c ...

  6. 基于mysqld_multi实现MySQL多实例配置

    环境: 操作系统  CentOS7.5(已安装MySQL) 主机名    localhost 本机安装路径为 /usr/local/mysql 实验初始配置:所有主机关闭防火墙与selinux [ro ...

  7. 攻防世界WEB新手练习

    0x01 view_source 0x02 get_post 这道题就是最基础的get和post请求的发送 flag:cyberpeace{b1e763710ff23f2acf16c2358d3132 ...

  8. CDH6.2的spark访问oss

    CDH6配置oss后:spark的配置 /opt/cloudera/parcels/CDH-6.2.0-1.cdh6.2.0.p0.967373/jars/opt/cloudera/parcels/C ...

  9. Flutter、Weex、RN,Native对比

  10. django fields lookup methods(lookup类型)

    __exact        精确等于 like 'aaa' __iexact    精确等于 忽略大小写 ilike 'aaa' __contains    包含 like '%aaa%' __ic ...