首页 > 编程知识 正文

分布式session框架,分布式解决方案

时间:2023-05-06 13:20:43 阅读:22942 作者:2532

建议您阅读

分布式会话的一致性?

简言之,这是服务器群集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 '当前项目端口:“projectPort '当前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;

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

由于正在使用默认轮询机制,因此下一次访问的是8080端口。 刚才保存的值http://www.hello.com/getSession当前项目端口: 8080直接获取来自当前session id 3360 c 6663 ea 93572 FB 8da e 27736 a 553 eab 89的名称

此时,我们发现8080端口没有我们保存的值,会话id也与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来进行测试:当前项目端口: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共享!

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