关于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中