springboot(十八)-session共享
前言
在传统的单服务架构中,一般来说,只有一个服务器,那么不存在 Session 共享问题,但是在分布式/集群项目中,Session 共享则是一个必须面对的问题,先看一个简单的架构图:
在这样的架构中,会出现一些单服务中不存在的问题,例如客户端发起一个请求,这个请求到达 Nginx 上之后,被 Nginx 转发到 Tomcat A 上,然后在 Tomcat A 上往 session 中保存了一份数据,下次又来一个请求,这个请求被转发到 Tomcat B 上,此时再去 Session 中获取数据,发现没有之前的数据。对于这一类问题的解决,思路很简单,就是将各个服务之间需要共享的数据,保存到一个公共的地方(主流方案就是 Redis):
当所有 Tomcat 需要往 Session 中写数据时,都往 Redis 中写,当所有 Tomcat 需要读数据时,都从 Redis 中读。这样,不同的服务就可以使用相同的 Session 数据了。
这样的方案,可以由开发者手动实现,即手动往 Redis 中存储数据,手动从 Redis 中读取数据,相当于使用一些 Redis 客户端工具来实现这样的功能,毫无疑问,手动实现工作量还是蛮大的。
一个简化的方案就是使用 Spring Session 来实现这一功能,Spring Session 就是使用 Spring 中的代理过滤器,将所有的 Session 操作拦截下来,自动的将数据 同步到 Redis 中,或者自动的从 Redis 中读取数据。
对于开发者来说,所有关于 Session 同步的操作都是透明的,开发者使用 Spring Session,一旦配置完成后,具体的用法就像使用一个普通的 Session 一样。
实战
1.创建一个springboot项目,添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.javaboy</groupId>
<artifactId>sessionshare</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sessionshare</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency> </dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>
2.配置application.properties或者.yml文件
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.redis.database=0 server.port=8082
我们再这个文件中配置下redis。
3.提供接口文件
package org.javaboy.sessionshare; import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpSession; @RestController
public class HelloController {
@Value("${server.port}")
Integer port; @GetMapping("/set")
public String set(HttpSession session) {
session.setAttribute("user", "javaboy");
return String.valueOf(port);
} @GetMapping("/get")
public String get(HttpSession session) {
return session.getAttribute("user") + ":" + port;
}
}
简单说下,@Value("{server.port}") 如果我们不指定端口,直接启动该实例,那么port = 8082 (application.properties文件中有写),如果我们指定端口启动该实例,那port就是我们指定的端口了。具体的用法下面有。
我们只提供两个接口,一个set和一个get。字面上就能明白,不做赘言。
4.启动类
package org.javaboy.sessionshare; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class SessionshareApplication { public static void main(String[] args) {
SpringApplication.run(SessionshareApplication.class, args);
} }
测试
启动redis服务
我们在终端cd 到项目目录
mvn install
java -jar target/sessionshare-0.0.1-SNAPSHOT.jar --server.port=8080
再启动一个终端cd 到项目目录
java -jar target/sessionshare-0.0.1-SNAPSHOT.jar --server.port=8081
指定端口启动两个实列。
浏览器访问 localhost:8080/set , 你会看到页面上显示8080,我们已经set完了。数据已经保存到redis中。
然后访问 localhost:8081/get , 看到页面上显示
javaboy:8081
说明我们取到了redis中的数据。
此时关于 session 共享的配置就已经全部完成了,session 共享的效果我们已经看到了,但是每次访问都是我自己手动切换服务实例,因此,接下来我们来引入 Nginx ,实现服务实例自动切换。
引入 Nginx
编辑 nginx.conf 文件:
upstream springboot{
server 127.0.0.1:8080 weight=1;
server 127.0.0.1:8081 weight=2;
} server {
listen 9000;
server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / {
proxy_pass http://springboot;
}
在这段配置中:
- upstream 表示配置上游服务器
- springboot表示服务器集群的名字,这个可以随意取名字
- upstream 里边配置的是一个个的单独服务
- weight 表示服务的权重,意味者将有多少比例的请求从 Nginx 上转发到该服务上
- location 中的 proxy_pass 表示请求转发的地址,
/
表示拦截到所有的请求,转发转发到刚刚配置好的服务集群中
配置完成后,启动nginx,和上面两个springboot实例。
因为我的nginx端口是9000,且在本地,
多次访问localhost:9000/set,多次访问localhost:9000/get.
看页面结果,我们即实现了redis中保存和读取session中的值,也实现了负载均衡。
2 总结
本文主要向大家介绍了 Spring Session 的使用,另外也涉及到一些 Nginx 的使用 ,虽然本文较长,但是实际上 Spring Session 的配置没啥。
我们写了一些代码,也做了一些配置,但是全都和 Spring Session 无关,配置是配置 Redis,代码就是普通的 HttpSession,和 Spring Session 没有任何关系!
唯一和 Spring Session 相关的,可能就是我在一开始引入了 Spring Session 的依赖吧!
如果大家没有在 SSM 架构中用过 Spring Session ,可能不太好理解我们在 Spring Boot 中使用 Spring Session 有多么方便,因为在 SSM 架构中,Spring Session 的使用要配置三个地方 ,一个是 web.xml 配置代理过滤器,然后在 Spring 容器中配置 Redis,最后再配置 Spring Session,步骤还是有些繁琐的,而 Spring Boot 中直接帮我们省去了这些繁琐的步骤!不用再去配置 Spring Session。
代码下载地址:https://gitee.com/fengyuduke/my_open_resources/blob/master/sessionshare.zip
本文出处:https://www.cnblogs.com/lenve/p/10971384.html#4272530
springboot(十八)-session共享的更多相关文章
- 基于SpringBoot+Redis的Session共享与单点登录
title: 基于SpringBoot+Redis的Session共享与单点登录 date: 2019-07-23 02:55:52 categories: 架构 author: mrzhou tag ...
- springboot+redis实现session共享
1.场景描述 因项目访问压力有点大,需要做负载均衡,但是登录使用的是公司统一提供的单点登录系统,需要做session共享,否则假如在A机器登录成功,在B机器上操作就会存在用户未登录情况. 2. 解决方 ...
- SpringBoot(十八)_springboot打成war包部署
最近在做项目的时候,由于使用的是springboot,需要打成war包.我就按照正常的思路去打包,结果部署后无法访问,一直报错404.后续问了问 公司同事,他给解决了.说大部分都是这个原因. 如果需要 ...
- SpringBoot(十八):SpringBoot2.1.1引入SwaggerUI工具
Swagger是一个有用web界面的提供实体模型结构展示,接口展示,调测等的一个工具,使用它可以提高开发者开发效率,特别是前后端配合开发时,大大省去了沟通接口耗费的时间:服务端开发完接口发布后,UI端 ...
- springboot(十八):解决跨域问题
在controller上添加@CrossOrigin注解,如下: @RestController @RequestMapping("course") @CrossOrigin pu ...
- springboot(十八):CORS方式实现跨域
资料 https://www.cnblogs.com/toutou/p/9843588.html
- 从.Net到Java学习第八篇——SpringBoot实现session共享和国际化
从.Net到Java学习系列目录 SpringBoot Session共享 修改pom.xml添加依赖 <!--spring session--> <dependency> & ...
- 学习Spring Boot:(十八)Spring Boot 中session共享
前言 前面我们将 Redis 集成到工程中来了,现在需要用它来做点实事了.这次为了解决分布式系统中的 session 共享的问题,将 session 托管到 Redis. 正文 引入依赖 除了上篇文章 ...
- Spring Boot2 系列教程(二十八)Spring Boot 整合 Session 共享
这篇文章是松哥的原创,但是在第一次发布的时候,忘了标记原创,结果被好多号转发,导致我后来整理的时候自己没法标记原创了.写了几百篇原创技术干货了,有一两篇忘记标记原创进而造成的一点点小小损失也能接受,不 ...
随机推荐
- LeetCode 82. 删除排序链表中的重复元素 II(Remove Duplicates from Sorted List II)
题目描述 给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字. 示例 1: 输入: 1->2->3->3->4->4->5 输出: ...
- 用Java实现一个二叉树
介绍 使用Java实现一个int值类型的排序二叉树 二叉树 二叉树是一个递归的数据结构,每个节点最多有两个子节点. 通常二叉树是二分查找树,每个节点它的值大于或者等于在它左子树节点上的值,小于或者等于 ...
- SolrCloud配置
一.简介 Apache Solr是基于Lucene的全文搜索引擎.如何让Solr具有容错性和高可用性,SolrCloud可以帮助我们搭建集群,提供分布式索引,以及自动备份.SolrCloud是Solr ...
- Spring Bean学习创建及使用<一>
转自:http://glzaction.iteye.com/blog/1299441 Spring中依赖注入有三种注入方式: 一.构造器注入: 二.设值注入(setter方式注入): 三.Feild方 ...
- Card 卡片
将信息聚合在卡片容器中展示. 基础用法 包含标题,内容和操作. Card 组件包括header和body部分,header部分需要有显式具名 slot 分发,同时也是可选的. <el-card ...
- Android studio2 中的 SDK Manager的使用-------Android SDK 的安装与更新(Install missing platform(s) and sync project 编译错误解决)
最近在编写Android程序,其中有一个问题就是对旧应用的导入,此时往往你的Android SDK中并没有老版本的Android SDK, 此时往往会提示你出现错误 Install missing p ...
- How to run a VBA macro when new mail is received in Outlook
It can be very useful to run a VBA macro when new mail is received in Outlook. A customer asked me t ...
- 阶段3 3.SpringMVC·_07.SSM整合案例_05.ssm整合之Spring整合SpringMVC的框架
点击超连接,执行controller里面的方法 那么就需要在Controller里面定义Service对象,就需要依赖注入进来. 启动tomcat服务器,web.xml里面的前端控制器会帮我加载spr ...
- pyqt5的QListWidget中设置右键菜单
QListWidget 是继承 QWidget 的, 所以 QListWidget 是有右键菜单的, 从文档上可以找到 QWidget 上有以下两个与右键菜单有关的函数: Qt.ContextMenu ...
- ListView中用鼠标拖动各项上下移动的问题。(100分)
在OnDragDrop事件中處理:以下是delphi的例子 procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: Integ ...