虽然我的CRM系统现在还没有使用负载均衡,没有使用多机。但是session共享是必须要考虑的事情。各位可能都是大牛,但是保不齐有不知道的,先介绍下负载均衡和session共享方面的知识:
由于我们的用户越来越多,并发量越来越高,一台机器无法应付所有请求,获取为了系统安全,一台机器坏了,网站系统还能正常访问,我们可以考虑用nginx做负载均衡服务器,将请求分发到不同的tomcat服务器处理(本处只介绍nginx做负载均衡tomcat做java服务器),集群框架如下图所示:
从图中我们看出负载均衡后,我们的请求会分发到其中的一个tomcat中去,我们知道session是在机器的内存中,那么由于我们的连续请求可能是在不同的机器去处理,那么很可能前一次请求的session后一次无法取得,如何解决这个问题?redis为我们提供了很好的session共享方案。
我们的CRM是采用spring boot 开发的,在spring boot里面可以非常方便的集成redis,通过redis实现session共享,下面我就给大家介绍下具体的实现。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<!--<version>1.0.2.RELEASE</version>-->
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<!--<version>2.8.0</version>-->
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>1.5.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<!-- alibaba的druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.11</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</dependency>
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.9</version>
</dependency>
</dependencies>
以上是maven 的pom依赖设置,和redis相关的是
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
spring-session-data-redis 支持redis session 共享
application.yml 配置如下,这个配置让我们的系统客户获取redis的连接。
- logging:
- config: classpath:logback.xml
- path: d:/logs
- server:
- port: 8080
- session-timeout: 60
- spring:
- redis:
- database: 0
- host: 127.0.0.1
- port: 6379
- password:
- timeout: 0
- pool:
- max-active: 8
- max-wait: -1
- max-idle: 8
- min-idle: 0
- session:
- store-type: none
有点朋友是用application.properties的,只是编写的结构不一样,内容一一对应就好了。
接下来就是编写config文件,使我们的系统能支持redis缓存session共享
新建一个java文件
package com.hzucan.crmConfig; import org.springframework.context.annotation.Configuration; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; /** * Created by tongjianbin on 18/4/17. */ @Configuration @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800) public class RedisSessionConfig { }
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
用于指定sess的过期时间,默认是30分钟,可以按系统的实际情况改写maxInactiveIntervalInSeconds,设置session过期时间。
在写完配置类后,前万记得要在在spring boot的启动类上写上注解@EnableRedisHttpSession
@SpringBootApplication @EnableCaching @EnableRedisHttpSession @EnableTransactionManagement @ComponentScan(basePackages = "com.hzucan") @MapperScan(basePackages = "com.hzucan.mapper") @EntityScan(basePackages = "com.hzucan.entity") public class Entry { public static void main(String[] args) throws Exception{ SpringApplication.run(Entry.class,args); } }
接下来写一个测试类来进行测试
@EnableRedisHttpSession @Controller @RequestMapping(value= "/") public class IndexController { @Autowired private UserService userService; @Autowired HttpServletRequest request; @Autowired HttpServletResponse response; @Autowired HttpSession httpSession; @RequestMapping(value="/getSessionId") @ResponseBody public String getSessionId(HttpServletRequest request){ Object o = httpSession.getAttribute("springboot"); if(o == null){ o = "spring boot 牛逼了!!!有端口"+request.getLocalPort()+"生成"; httpSession.setAttribute("springboot", o); } return "端口=" + request.getLocalPort() + " sessionId=" + request.getSession().getId() +"<br/>"+o; }}
启动springboot, 访问http://localhost:8080/getSessionId
网页上显示如下内容:
端口=8080 sessionId=5F1FB48698294843039010C1B8253B0D
spring boot 牛逼了!!!有端口8080生成
我们再查看redis
当session 失效的时候,我们再查看redis,发现session相关的key已经没有了,虽然我们这里是使用了单台设备,但是通过看key是否存在redis里面,可以大致证明是否实现 了redis session共享,因为虽然负责均衡会让我们的请求转发到不同的服务器,但是cookie里面的sessionId是不会变的,都会到同一个redis里面去查询session。
好了,到此已经在我的crm里面通过redis 实现了session共享。