spring boot+redis+spring session+Nginx实现负载均衡下session共享

关于Nginx的介绍不懂的可以看下我之前的博客Linux下使用Nginx实现负载均衡其中讲解的什么是Nginx以及如何使用。

问题描述:在目前的微服务+分布式下我们大多会面临一个问题:例如客户端发出一个请求到Nginx,Nginx根据自己的负载均衡策略分发到了tomcatA上面,然后tomcatA上往session保存了一份数据。过了一会客户端又发出一个请求,Nginx分给了tomcatB,此时在tomcatB中去读取session数据发现并没有之前的数据。为了解决这样的问题我们就需要做到session共享。也就是说不管在哪个tomcat下都可以访问到我们的公共session以便读取数据。

解决的方法:很简单,就是第一次存的session数据直接存到redis中,以后每次读数据都直接从redis中读,这样即使是不同的服务也可以共享session了。这种方案可以由开发者手动实现,即手动存,手动读,毫无疑问,工作量略大。

简化的方案就是通过spring session来实现。spring session会将所有的session操作拦截下来,自动将数据同步到redis,或者从redis中读取。实际操作如下。

前提:安装redis、安装Nginx

首先引入依赖(我是直接在之前的一个spring boot的Demo中测试的中间有些代码是没必要的 所以这里我只贴一些关于本次测试的代码)

        <!--redis 配置-->
		<dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
		<!--redis session 共享-->
		<dependency>
		    <groupId>org.springframework.session</groupId>
		    <artifactId>spring-session-data-redis</artifactId>
		</dependency>

application.yml添加redis配置

spring:
  redis:
       database: 0
 # Redis服务器地址
       host: 127.0.0.1
 # Redis服务器连接端口
       port: 6379  
 # Redis服务器连接密码(默认为空)
       password:  
 # 连接池最大连接数(使用负值表示没有限制)
       pool: 
         max-active: 8  
 # 连接池最大阻塞等待时间(使用负值表示没有限制)
         max-wait: -1  
 # 连接池中的最大空闲连接
         max-idle: 8  
 # 连接池中的最小空闲连接
         min-idle: 0  
       cluster:
         max-redirects: 10
         nodes: 127.0.0.1:6080
 # 连接超时时间(毫秒)
       timeout: 2000

例如我的项目名为SpringBootDemo,直接复制一版SpringBootDemo2更改一下端口号,我的是一个为8080一个为8081,具体如下图

controller1中测试代码

	/**
	 * http://localhost:8080/login/setSession 
	 * @param request
	 * @return
	 */
	@RequestMapping("/setSession")
	@ResponseBody
	public String login(HttpServletRequest request) {
		request.getSession().setAttribute("zhoukaishun", request.getSession().getId());
		return request.getSession().getId()+"---端口8080下set Session";
	}
	/**
	 * http://localhost:8080/login/getSession 
	 * @param request
	 * @return
	 */
	@RequestMapping("/getSession")
	@ResponseBody
	public String getSession(HttpServletRequest request) {
		return request.getSession().getAttribute("zhoukaishun")+"---端口8080下get Session";
	}

controller2中测试代码(controller1和controller2属于两个服务,2就是1的复制版稍作改动用于方便测试)

/**
	 * http://localhost:8081/login/setSession 
	 * @param request
	 * @return
	 */
	@RequestMapping("/setSession")
	@ResponseBody
	public String login(HttpServletRequest request) {
		request.getSession().setAttribute("zhoukaishun", request.getSession().getId());
		return request.getSession().getId()+"---端口8081下set Session";
	}
	/**
	 * http://localhost:8081/login/getSession 
	 * @param request
	 * @return
	 */
	@RequestMapping("/getSession")
	@ResponseBody
	public String getSession(HttpServletRequest request) {
		return request.getSession().getAttribute("zhoukaishun")+"---端口8081下get Session";
	}

配置Nginx安装目录下conf下的nginx.conf

upstream 表示配置上游服务器
mydata 表示服务器集群的名字(名字可以随意取,和下面对应就可以)
upstream 里边配置的是一个个的单独服务
weight 表示服务的权重,意味者将有多少比例的请求从 Nginx 上转发到该服务上
location 中的 proxy_pass 表示请求转发的地址,/ 表示拦截到所有的请求,转发转发到刚刚配置好的服务集群中
proxy_redirect 表示设置当发生重定向请求时,nginx 自动修正响应头数据(默认是 Tomcat 返回重定向,此时重定向的地址是 Tomcat 的地址,我们需要将之修改使之成为 Nginx 的地址,如果使用“default”参数,将根据location和proxy_pass参数的设置来决定 )

启动Nginx,启动redis,启动两个项目

先输入  localhost:80/login/setSession

然后输入  localhost:80/login/getSession

反复刷新页面可得出8080端口服务与8081端口服务交替出现切session值相同,redis中

参考博客:https://blog.csdn.net/Websphere_zxf/article/details/97764860

发布了20 篇原创文章 · 获赞 58 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/zks_4826/article/details/98050863
今日推荐