首页 > 编程知识 正文

java分布式架构,分布式事务redis解决方案

时间:2023-05-06 10:08:07 阅读:32042 作者:2407

SpringBoot分布式会话共享解决方案

分布式会话的一致性?

简言之,这是服务器集群会话共享的问题。 对于集群,Session存储在各自服务器的tomcat中,如果向不同的服务分发地址时无法获取sesson,则会出现Session共享问题。

会话的作用?

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

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

分布式会话有什么问题?

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

解决方案:使用cookie执行。 很明显,这种不安全的操作是不可靠的)

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

使用数据库同步会话(效率低、访问压力大) ) ) ) ) ) ) ) )。

使用tomcat中的内置session同步(可能会导致同步延迟的群集过多的tomcat、session全局复制导致性能下降) ) ) )。

用token代替session

使用与spring-session集成的解决方案存储在redis中(读写效率高,可在群集环境中实现高可用性) )。

spring-session实战

将两个SpringBoot项目的端口号分别设置为8080和8090开始测试。

1、项目取决于//springboot和redis APP应用的基本环境配置

compile ' org.spring framework.boot : spring-boot-starter-data-redis :2.1.4.release '

//springsession和redis适用基本的环境构成

compile ' org.spring framework.session : spring-session-data-redis 33602.1.5.release '

2、测试类@RestController

@requestmapping(/test ) )。

publicclassTestController{

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

私有项目端口;

@获取映射(/create session ) )。

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

sssion.setattribute('name ',name );

return '当前项目端口: " projectPort "当前会话id:' session.getid () "已成功保存到session! ';

}

@getmapping(/getsession ) )。

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

return '当前项目端口:来自" projectPort "当前sessionId:' session.getId () "的名称: " session.getattribute () ) name "

}

}

3、yml文件的配置

为了演示的目的,仅端口不同,就配置了两个yml文件。

高速APP.yml server :

port:8080

spring:

redis:

host:127.0.0.1

port:6379

APP-8090.yml server :

port:8090

spring:

redis:

host:127.0.0.1

port:6379

4、启动类

将@EnableRedisHttpSession添加到Spring boot文档中,打开` spring session '支持。 配置如下: @SpringBootApplication

@EnableRedisHttpSession

publicclassAppRun{

public static void main(String[] args) {

SpringApplication.run(AppRun.class, args);

}

}

这样以来,最简单的 Spring boot + redis 实现 session 共享就完成了,下面进行下测试。

5、测试

首先我们开启两个 tomcat 服务,端口分别为 8080 和 8090。

启动之后进行访问测试,首先访问 8080 端口的 tomcathttp://localhost:8080/test/createSession

然后访问 8080 端口的 getSessionhttp://localhost:8080/test/getSession

然后再访问 8090 端口的 getSessionhttp://localhost:8090/test/getSession

可见,8080与9090两个服务器返回结果一样,实现了session的共享。

6、redis 查看

查看 redis 时,注意到生成了 3 个key。包含了过期时间,sessionId等。127.0.0.1:6379> keys *

1) "spring:session:expirations:1557234900000"

2) "spring:session:sessions:expires:70c59a29-e6ef-4d4f-825d-03dae4502686"

3) "spring:session:sessions:70c59a29-e6ef-4d4f-825d-03dae4502686"

127.0.0.1:6379> hkeys spring:session:sessions:70c59a29-e6ef-4d4f-825d-03dae4502686

1) "creationTime"

2) "maxInactiveInterval"

3) "lastAccessedTime"

4) "sessionAttr:name"

因为 session 是存储在 redis 中,所以,当我把 8080 和 8090 服务器同时停掉之后,再重新启动,然后刷新浏览器中的响应,session 依然可以获取得到。这就保证了用户在登录后,重新启动服务器 session 不会失效的问题。

@EnableRedisHttpSession 注解

在上面的启动类中,用到了 @EnableRedisHttpSession 的注解,查看源码注意到它有 4 个参数让我们使用。public @interface EnableRedisHttpSession {

/**

* 会话超时(以秒为单位)。 默认情况下,它设置为1800秒(30分钟)

*/

int maxInactiveIntervalInSeconds() default MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;

/**

* 为 redis key 定义唯一的命名空间,默认前缀是 spring:session:

*/

String redisNamespace() default RedisOperationsSessionRepository.DEFAULT_NAMESPACE;

/**

* Redis会话的刷新模式。 默认为 ON_SAVE,另一个是 IMMEDIATE

*/

RedisFlushMode redisFlushMode() default RedisFlushMode.ON_SAVE;

/**

* 过期会话清理的cron表达式。 默认情况下每分钟运行一次

*/

String cleanupCron() default RedisHttpSessionConfiguration.DEFAULT_CLEANUP_CRON;

}

比如设置@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 7200)

Spring Session 的两种刷新模式 RedisFlushMode,参考文章:http://www.ibloger.net/article/3360.html

nginx 集群配置

通过spring boot + redis来实现session的共享非常简单,而且用处也极大,配合nginx进行负载均衡,便能实现分布式的应用了。

例如开启 nginx 集群配置如下:# 默认使用轮询,

upstream backserver{

server 127.0.0.1:8080;

server 127.0.0.1:8090;

}

# 修改server中的local

location / {

proxy_pass  http://backserver;

...

}

Gitee源码

https://gitee.com/liurenkui/springboot-session-demo

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