Cloud++:SpringCloud Gateway WebSession 笔记

刚接触到 gateway 的时候难免会遇到一些坎坷,特此写下笔记。

WebSession:

以往用 zuul 作网关的时候,直接使用 @EnableRedisHttpSession 在配置里面就可以通过 redis 共享 session 信息

spring 同时提供了 EnableRedisWebSession 来对 WebFlux 的支持

session 的jar包引入POM:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-core</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

添加 redis 配置:

spring:
  redis:
    host: 192.168.1.101
    port: 6379
    timeout: 20000
    pool:
      # 连接池最大连接数(使用负值表示没有限制)
      max-active: 8
      # 连接池中的最小空闲连接  
      min-idle: 0
      # 连接池中的最大空闲连接
      max-idle: 8
      # 连接池最大阻塞等待时间(使用负值表示没有限制)
      max-wait: 5000
    password:

然后在 filter 里面配置:

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String url = request.getURI().getPath();
        return exchange.getSession().flatMap(webSession -> {
            LOGGER.info("websession: {}", webSession.getId());
            webSession.getAttributes().put(webSession.getId(), "sign");
            return chain.filter(exchange);
        }).then(Mono.fromRunnable(() -> {
            LOGGER.info("this is a post filter");
        }));
    }

 请求经过filter的时候,会将 webSession.getAttributes().put(webSession.getId(), “sign”); 存入redis

 

 

可以看到刚才保存进去的数据:

但是这里有一个问题,直接这样存储的数据,由于 Gateway 使用 Netty 作为容器,转发的时候 sessionId 已经发生了变化,所以下游服务并不能获取到正确的 sessionId

网关中的 sessionId:

下游的 sessionId:

使用 Gateway 只能用 token 的方案,不能用浏览器自身的 session 作为客户端凭证的方案 例如在 heade r里面加入 token 的头 存入到 redis 中。

之后的请求都携带 token 信息作为凭证,如何运用 token 这里就不叙述了。

- - - 

另外在实际使用中,发现低版本的lettuce存在严重bug,会有redis里面存在数据但读出来为null的情况

这种情况在lettuce的github上也有看到issue

https://github.com/lettuce-io/lettuce-core/pull/987

在5.1.5.RELEASE已经修复,在实际使用的时候需要注意尽量引用高版本的。

使用Springboot 2.1.5.RELEASE版自动依赖的就是5.1.6.RELEASE版本的lettuce

目前webflux相关的组件感觉还是没有完全成熟,使用的时候可能还是会遇到比较多的坑。

原文地址:https://www.cnblogs.com/codingmode/p/15333160.html