首页 > 编程知识 正文

分布式事务和分布式锁的关系,集群中session如何实现共享

时间:2023-05-04 11:09:19 阅读:31992 作者:2821

分布式会话的一致性?

简言之,这是服务器群集Session共享的问题

会话的作用?

Session是客户端和服务器通信会话跟踪技术,服务器和客户端存储整个通信的会话基本信息。

客户端首次访问服务端时,服务端会响应会话id将其存储在本地cookie中,然后在后续访问中将cookie的会话id放在请求标头中以访问该服务。 如果在此sessionId中找不到相应的数据,则服务将创建新的sessionId并响应客户端。

分布式会话有什么问题?

假设首先访问服务a,生成Sessionid并将其存储在cookie中,然后第二次访问服务b的客户端在cookie中读取Sessionid并将其添加到请求标头中。 如果在服务b中找不到通过sessionid对应的数据,则必须创建新的sessionid并将其返回给客户端,不能共享session

解决方案:

使用cookie进行(显然这种不安全的操作不可靠)。

使用Nginx绑定策略,同一ip只能在指定的同一台计算机上访问。 不支持负载平衡。

利用数据库同步会话(效率低下) ) ) ) )。

使用tomcat内置的会话同步(同步可能会延迟)

用token代替session

我们使用与spring-session集成的解决方案存储在redis中

项目中存在的问题

启动两个项目的端口号分别为8080、8081。

依赖关系:

org.spring帧work.boot

spring-boot-starter-parent

2.1.1 .发布

org.spring帧work.boot

spring-boot-starter-web

创建测试类:

//*

* Author: SimpleWu

* date: 2018/12/14

*/

@ rest控制器

publicclasstestsessioncontroller {

@value((${server.port} ) ) )。

私有集成器项目端口; //项目端口

@请求映射(/create session ) )。

发布会话创建会话(http会话会话,字符串名称)。

sssion.setattribute('name ',name );

return '当前项目端口:“项目”当前SessionId :' session.getId ()已成功保存到session! ';

}

@requestmapping(/getsession ) )。

公共字符串获取(http会话会话) {

return '当前项目端口:名称: ' session.getid (),来自" projectPort "当前session id : ' session.getattribute ) ) name

}

}

yml配置:

服务器:

port: 8080

修改映射文件

#将本机ip映射到www.hello.com

127.0.0.1 www.hello.com

在此打开nginx群集并更改配置。

#加入

#默认情况下使用轮询,

upstream backserver{

服务器127.0.0.1:8080;

server 127.0.0.1:8081;

}

修改服务器的本地

位置/{

proxy _ pass http://后台服务器;

索引索引. html index.htm;

}

要通过直接轮询机制进行访问,请首先在Session中输入名称。 http://www.hello.com/create session? name=SimpleWu

当前项目端口: 8081当前session id :0 f 20 f 73170 AE 6780 B1 EC 06 d9b 06210 db已成功保存到session。

由于正在使用默认轮询机制,因此下一次访问的是8080端口。 直接获取刚才保存的值http://www.hello.com/getSession

当前项目端口: 8080当前se

ssionId :C6663EA93572FB8DAE27736A553EAB89 获取的姓名:null

这个时候发现8080端口中并没有我们存入的值,并且sessionId也是与8081端口中的不同。

别急继续访问,因为轮询机制这个时候我们是8081端口的服务器,那么之前我们是在8081中存入了一个姓名。那么我们现在来访问以下看看是否能够获取到我们存入的姓名:SimpleWu,继续访问:http://www.hello.com/getSession

当前项目端口:8081 当前sessionId :005EE6198C30D7CD32FBD8B073531347 获取的姓名:null

8080端口我们没有存入连8081端口存入的都没有呢?

我们仔细观察一下第三次访问8081的端口sessionid都不一样了,是因为我们在第二次去访问的时候访问的是8080端口这个时候客户端在cookie中获取8081的端口去8080服务器上去找,没有找到后重新创建了一个session并且将sessionid响应给客户端,客户端又保持到cookid中替换了之前8081的sessionid,那么第三次访问的时候拿着第二次访问的sessionid去找又找不到然后又创建。一直反复循环。

如何解决这两个服务之间的共享问题呢?

spring已经给我们想好了问题并且已经提供出解决方案:spring-session 不了解的可以去百度了解下。

我们首先打开redis并且在pom.xml中添加依赖:

com.alibaba

fastjson

1.2.47

org.springframework.boot

spring-boot-starter-data-redis

org.springframework.session

spring-session-data-redis

org.apache.commons

commons-pool2

redis.clients

jedis

修改yml配置文件:

server:

port: 8081

spring:

redis:

database: 0

host: localhost

port: 6379

jedis:

pool:

max-active: 8

max-wait: -1

max-idle: 8

min-idle: 0

timeout: 10000

redis:

hostname: localhost

port: 6379

#password: 123456

添加Session配置类

/**

* Author: SimpleWu

* date: 2018/12/14

*/

//这个类用配置redis服务器的连接

//maxInactiveIntervalInSeconds为SpringSession的过期时间(单位:秒)

@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)

public class SessionConfig {

// 冒号后的值为没有配置文件时,制动装载的默认值

@Value("${redis.hostname:localhost}")

private String hostName;

@Value("${redis.port:6379}")

private int port;

// @Value("${redis.password}")

// private String password;

@Bean

public JedisConnectionFactory connectionFactory() {

JedisConnectionFactory connection = new JedisConnectionFactory();

connection.setPort(port);

connection.setHostName(hostName);

//connection.setPassword(password);

// connection.setDatabase(0);

return connection;

}

}

初始化Session配置

/**

* Author: SimpleWu

* date: 2018/12/14

*/

//初始化Session配置

public class SessionInitializer extends AbstractHttpSessionApplicationInitializer {

public SessionInitializer() {

super(SessionConfig.class);

}

}

然后我们继续启动8080,8081来进行测试:

首先存入一个姓名http://www.hello.com/createSession?name=SimpleWu:

当前项目端口:8080 当前sessionId :cf5c029a-2f90-4b7e-8345-bf61e0279254在Session中存入成功!

应该轮询机制那么下次一定是8081,竟然已经解决session共享问题了那么肯定能够获取到了,竟然这样那么我们直接来获取下姓名http://www.hello.com/getSession:

当前项目端口:8081 当前sessionId :cf5c029a-2f90-4b7e-8345-bf61e0279254 获取的姓名:SimpleWu

这个时候我们发现不仅能够获取到值而且连sessionid都一致了。

实现原理:

就是当Web服务器接收到http请求后,当请求进入对应的Filter进行过滤,将原本需要由web服务器创建会话的过程转交给Spring-Session进行创建,本来创建的会话保存在Web服务器内存中,通过Spring-Session创建的会话信息可以保存第三方的服务中,如:redis,mysql等。Web服务器之间通过连接第三方服务来共享数据,实现Session共享!

​到此这篇关于详解Java分布式Session共享解决方案的文章就介绍到这了,更多相关Java分布式Session共享内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。