分布式session之redis解決方案實現


 

一、首先Session

 

Session 是客戶端與服務器通訊會話技術, 比如瀏覽器登陸、記錄整個瀏覽會話信息。session存放在服務器,關閉瀏覽器不會失效。

Session實現原理

客戶對向服務器端發送請求后,Session 創建在服務器端,返回Sessionid給客戶端瀏覽器保存在本地,當下次發送請求的時候,在請求頭中傳遞sessionId獲取對應的從服務器上獲取對應的Sesison

 

 

請求過程: 

 服務器端接受到客戶端請求,會創建一個session,使用響應頭返回 sessionId給客戶端。客戶端獲取到sessionId后,保存到本地。

下次請求:客戶端將本地的sessionId通過請求頭發送到服務器。服務器從請求頭獲取到對應的sessionId,使用sessionId在本地session內存中查詢。

 

 

HttpSession session = request.getSession();  //默認創建一個session  默認值為true  沒有找到對應的session 自動創建session

HttpSession session = request.getSession(false) //true的情況是 客戶端使用對應的sessionId查詢不到對應的session 會直接創建一個新的session  如果有的話直接覆蓋之前的

                                                                               //false               客戶端使用對應的sessionId查詢不到對應的session   不會創建新的session

 

    session 包括 sessionId和sessionValue    

    session本身是臨時的  token(令牌)與  sessionId很相似   保證了臨時且唯一

    

玩下session:

前提需要安裝nginx

配置如下:

 

host文件:c:\windows\system32\drivers\etc

訪問 www.toov5.com時候 走的nginx的服務器域名 然后默認監聽的端口號80。 進而通過配置upstream 負載均衡!

 

lz在玩時候,弄到了半夜,也沒排查出來原因,媽的氣死了! 地址寫成了 127.0.0.1  

yml:

server:
  port: 8080  

pom:

 

<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>
  <groupId>com.toov5.loveCode</groupId>
  <artifactId>loveCode</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<properties>
		<weixin-java-mp.version>2.8.0</weixin-java-mp.version>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
		<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.build.locales>zh_CN</project.build.locales>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<!-- <exclusions> <exclusion> <groupId>com.fasterxml.jackson.core</groupId> 
				<artifactId>jackson-databind</artifactId> </exclusion> </exclusions> -->
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.47</version>
		</dependency>
		<!-- Testing Dependencies -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
		<!--spring session 與redis應用基本環境配置,需要開啟redis后才可以使用,不然啟動Spring boot會報錯 -->
		<!-- <dependency>
			<groupId>org.springframework.session</groupId>
			<artifactId>spring-session-data-redis</artifactId>
		</dependency> -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-pool2</artifactId>
		</dependency>
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
		</dependency>

	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<maimClass>com.meiteedu.WxMpApplication</maimClass>
				</configuration>
				<executions>
					<execution>
						<goals>
							<goal>repackage</goal>
						</goals>
					</execution>
				</executions>

			</plugin>
		</plugins>
	</build>
  
</project>

  

服務器端代碼:

package com.toov5.loveCode;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class TestSessionController {
    @Value("${server.port}")
    private String serverPort;

    @RequestMapping("/")
    public String index() {
        return serverPort;
    }

    // 創建session 會話
    @RequestMapping("/createSession")
    public String createSession(HttpServletRequest request, String nameValue) {
        // 默認 創建一個session,
        HttpSession session = request.getSession();
        System.out.println(
                "存入Session  sessionid:信息" + session.getId() + ",nameValue:" + nameValue + ",serverPort:" + serverPort);
        session.setAttribute("name", nameValue);
        return "success-" + serverPort;
    }

    // 獲取session 會話
    @RequestMapping("/getSession")
    public Object getSession(HttpServletRequest request) {
        // 設置為true 情況下的時候,客戶端使用對應的sessionid 查詢不到對應的sesison 會直接創建一個新的session
        // 設置為false 情況下的時候,客戶端使用對應的sessionid 查詢不到對應的sesison 不 會直接創建一個新的session
        HttpSession session = request.getSession(true);
        if (session == null) {
            return serverPort + "  該服務器上沒有存放對應的session值";
        }
        System.out.println("獲取Session sessionid:信息" + session.getId() + "serverPort:" + serverPort);
        Object value = session.getAttribute("name");
        return serverPort + "-" + value;
    }

}

 

啟動類:啟動兩次 端口號修改8080、 8081

package com.toov5.loveCode;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@EnableAutoConfiguration
@SpringBootApplication
public class AppSession {

    public static void main(String[] args) {
        SpringApplication.run(AppSession.class, args);
    }

}

運行結果:8080 和 8081來回切換 負載均衡

調用服務器端方法: fist 存放在8080

查詢不到哦!

 

8081 沒有  就創建新的session  覆蓋原來的sessionId    true沒有就創建   

下次 又去8080 又沒有 又創建 來回折騰..............

此時:

修改false  沒有時候不創建 

 

然后傳入 value 然后繼續輪訓訪問;

 

二、分布式Session

        

       1、直接使用cookie替代session 不安全(存客戶端)

        2、Nginx的IP綁定  目的是同一個IP只能指定同一個機器訪問(相當於沒做集群了)

        3、 使用數據庫(效率低)

        4、tomcat內置Session同步,通過廣播可能產生延遲,占用帶寬

        5、使用 Spring-Session框架,相當於把session緩存緩存到redis中 (  緩存框架,緩存Session的值 )

        6、可以使用token替代session功能。自定義令牌替代session

 

 Spring-Session 重寫httpsession框架,將對應的值緩存到redis中,有點類似於一級、二級緩存。

 

必須要有的!

yml文件:

 

<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>
  <groupId>com.toov5.loveCode</groupId>
  <artifactId>loveCode</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<properties>
		<weixin-java-mp.version>2.8.0</weixin-java-mp.version>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
		<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.build.locales>zh_CN</project.build.locales>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<!-- <exclusions> <exclusion> <groupId>com.fasterxml.jackson.core</groupId> 
				<artifactId>jackson-databind</artifactId> </exclusion> </exclusions> -->
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.47</version>
		</dependency>
		<!-- Testing Dependencies -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
		<!--spring session 與redis應用基本環境配置,需要開啟redis后才可以使用,不然啟動Spring boot會報錯 -->
           <dependency>
			<groupId>org.springframework.session</groupId>
			<artifactId>spring-session-data-redis</artifactId>
		</dependency> 
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-pool2</artifactId>
		</dependency>
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
		</dependency>

	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<maimClass>com.meiteedu.WxMpApplication</maimClass>
				</configuration>
				<executions>
					<execution>
						<goals>
							<goal>repackage</goal>
						</goals>
					</execution>
				</executions>

			</plugin>
		</plugins>
	</build>
  
</project>

 非常非常重要的:一定要jredis引入  同時這個對session提供了大力支持哈哈

 

yml 的redis配置文件:

server:
  port: 8080

redis:
  hostname: 192.168.91.3     
  port:  6379
  password:  123

  

 后台業務邏輯:

package com.toov5.loveCode;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class TestSessionController {
    @Value("${server.port}")
    private String serverPort;

    @RequestMapping("/")
    public String index() {
        return serverPort;
    }

    // 創建session 會話
    @RequestMapping("/createSession")
    public String createSession(HttpServletRequest request, String nameValue) {
        // 默認 創建一個session,
        HttpSession session = request.getSession();
        System.out.println(
                "存入Session  sessionid:信息" + session.getId() + ",nameValue:" + nameValue + ",serverPort:" + serverPort);
        session.setAttribute("name", nameValue);
        return "success-" + serverPort;
    }

    // 獲取session 會話
    @RequestMapping("/getSession")
    public Object getSession(HttpServletRequest request) {
        // 設置為true 情況下的時候,客戶端使用對應的sessionid 查詢不到對應的sesison 會直接創建一個新的session
        // 設置為false 情況下的時候,客戶端使用對應的sessionid 查詢不到對應的sesison 不 會直接創建一個新的session
        HttpSession session = request.getSession(false);
        if (session == null) {
            return serverPort + "  該服務器上沒有存放對應的session值";
        }
        System.out.println("獲取Session sessionid:信息" + session.getId() + "serverPort:" + serverPort);
        Object value = session.getAttribute("name");
        return serverPort + "-" + value;
    }

}

配置:

package com.toov5.loveCode;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

//這個類用配置redis服務器的連接
//maxInactiveIntervalInSeconds為SpringSession的過期時間(單位:秒)
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SessionConfig {

    // 冒號后的值為沒有配置文件時,制動裝載的默認值
    @Value("${redis.hostname:localhost}")
    String HostName;
    @Value("${redis.port:6379}")
    int Port;
    @Value("${redis.password}") 
    String password;
    
    @Bean
    public JedisConnectionFactory connectionFactory() {
        JedisConnectionFactory connection = new JedisConnectionFactory();
        connection.setPort(Port);
        connection.setHostName(HostName);
        connection.setPassword(password);
        return connection;
    }
}

初始化:

package com.toov5.loveCode;

import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;

//初始化Session配置
public class SessionInitializer extends AbstractHttpSessionApplicationInitializer{
    public SessionInitializer() {
        super(SessionConfig.class);
    }
}

啟動類:

package com.toov5.loveCode;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@EnableAutoConfiguration
@SpringBootApplication
public class AppSession {

    public static void main(String[] args) {
        SpringApplication.run(AppSession.class, args);
    }

}

雖然是存放在8081,但是訪問時候 都有哦~ 大家試試玩玩吧~~

 

 引入的jar包重寫了 HttpSession類  去解決Session共享問題

而此時的:redis

控制台:

 

補充:

 Spring Boot 整合redis: 

 

server:
  port: 8080
spring:
  redis:
    database: 0   
    host:  192.168.91.3
    port:  6379
    password:  123
    jedis:
      pool:
        max-active: 8
        max-wait: -1
        max-idle: 8
        min-idle: 0
    timeout: 10000
redis:
  hostname: 192.168.91.3     
  port:  6379
  password:  123

  

 

 

   

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM