《果然新鲜》电商项目(34)-解决分布式Session共享问题

Posted IT刘老师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《果然新鲜》电商项目(34)-解决分布式Session共享问题相关的知识,希望对你有一定的参考价值。

文章目录

引言

本文主要解决分布式Session的问题。

1. 分布式Session的问题

1.首先在「果然新鲜电商」项目里复制一个portal-web,并修改端口号为8081,模拟门户集群,如下图:

2.项目新增controller,作为验证:

package com.guoranxinxian.web.controller;

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

import javax.servlet.http.HttpSession;

@RestController
public class TestSessionController 

    @Value("$server.port")
    private Integer projectPort;// 项目端口

    @RequestMapping("/createSession")
    public String createSession(HttpSession session, String name) 
        session.setAttribute("name", name);
        return "当前项目端口->" + projectPort + " sessionId->" + session.getId() + "在Session中存入成功!";
    

    @RequestMapping("/getSession")
    public String getSession(HttpSession session) 
        return "当前项目端口->" + projectPort + " sessionId->" + session.getId() + " 姓名->" + session.getAttribute("name");
    


3.nginx负载均衡配置:

#user  nobody;
worker_processes  1;

events 
    worker_connections  1024;

http 
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;


    keepalive_timeout  65;
  
    upstream  backServer
	    server 127.0.0.1:8080;
	    server 127.0.0.1:8081;
	
    server 
        listen       8099;
        server_name  127.0.0.1;
        location / 
           proxy_pass http://backServer;
           index  index.html index.htm;
              
    


4.浏览器请求获取session,浏览器请求http://127.0.0.1:8099/getSession

请求一次

请求二次

可以看到两次Session的id不一致,并不是我们想要的。那该如何解决呢?下面来讲解决方案。

2. 解决方案

解决方案有如下几种:

  • 使用cookie来完成(缺点:不安全,操作不可靠)
  • 使用Nginx中的ip绑定策略,同一个ip只能在指定的同一个机器访问(缺点:不支持负载均衡)
  • 利用数据库同步session(缺点:效率不高)
  • 使用tomcat内置的session同步(缺点:同步可能会产生延迟)
  • 使用token代替session(已经有很好的解决方案了,使用spring-session)
  • 我们使用spring-session以及集成好的解决方案,存放在redis中推荐)。

3. spring-session

step1:首先引入spring-session的maven依赖:

<!--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>

step2:配置Redis:

spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.jedis.pool.max-idle=100
spring.redis.jedis.pool.min-idle=1
spring.redis.jedis.pool.max-active=1000
spring.redis.jedis.pool.max-wait=-1

step3: 启动类声明允许使用Session共享:

package com.guoranxinxian;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class,
        DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class)
@EnableEurekaClient
@EnableFeignClients
//maxInactiveIntervalInSeconds为SpringSession的过期时间(单位:秒)
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class AppPortalWeb 

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

4. 测试

启动项目:

首先浏览器创建session并设置内容到session:http://127.0.0.1:8099/createSession?name=bruce

浏览器请求:http://127.0.0.1:8099/getSession,可以看到两次的sessionid均为:e9f48e08-9099-4472-adeb-bf34b3008004


打开Redis,可以看到redis已经保存了相关的redis的值:

总结

本文主要讲解分布式环境下,使用spring-session解决session共享的问题。

以上是关于《果然新鲜》电商项目(34)-解决分布式Session共享问题的主要内容,如果未能解决你的问题,请参考以下文章

《果然新鲜》电商项目(13)- 分布式配置中心Apollo安装配置

《果然新鲜》电商项目(15)- Apollo分布式配置中心管理Swagger

《果然新鲜》电商项目(11)- Docker搭建Maven私服仓库

《果然新鲜》电商项目(09)- Linux安装Docker

《果然新鲜》电商项目(10)- GitLab简介以及Docker部署

《果然新鲜》电商项目(20)- 项目配置信息分类(Apollo Namespace命名空间)