当前位置: 首页 > 知识库问答 >
问题:

Spring网关Redis会话存储类型-保存问题

强阳曜
2023-03-14

我有一个微服务架构中的spring网关。

当请求到达网关时,它必须以下面提到的方式进行操作

  1. 创建会话并设置属性
  2. 在redis中保存会话
  3. 将请求路由到Microservice B
  4. Microservice B接收会话ID并从会话获取属性

在尝试实现这一点时,(第2点)保存会话ID的操作发生在调用microservices B并返回其响应(第4点)之后。(即第2点发生在第4点之后)。

但是,在请求被路由到应用程序B之前,sessionId应该保存在redis中。

网关应用程序

应用yml

server:
  port: 4000
spring:
  cloud:
    gateway:
      routes:
      - id: demo-app1
        uri: http://localhost:4001/demo-app1
        predicates:
        - Path=/demo-app1/**
        filters:
        - SaveSession
        - CustomSessionHandle
        - name: Retry
          args:
            retries: 2
            statuses: BAD_GATEWAY
            methods: GET,POST
            backoff:
              firstBackoff: 10ms
              maxBackoff: 50ms
              factor: 2
              basedOnPreviousValue: false

  session:
    store-type: redis             # Defines where the session is stored JVM or redis
    redis:
      flush-mode: immediate      #Tells spring to flush the session data immediately into redis
  redis:
    host: 127.0.0.1
    port: 6379

@Component
public class CustomRequestFilter implements GatewayFilter, Ordered {

    @Override
    public int getOrder() {
        return -1;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Map<String, Object> sessionMap = new HashMap<>();
        sessionMap.put("param", "Hi, I am the value from cloud gateway");    

        return exchange.getSession().doOnNext(webSession -> webSession.getAttributes().putAll(sessionMap))).then(chain.filter(
                exchange));
    }

   
}

@Component
public class CustomSessionHandle extends AbstractGatewayFilterFactory<Object> {

    @Override
    public GatewayFilter apply(Object config) {
        return new CustomRequestFilter();
    }

}

POM文件--

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.zalando</groupId>
            <artifactId>logbook-spring-boot-starter</artifactId>
            <version>${logbook-spring-boot-starter}</version>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

共有2个答案

卢景澄
2023-03-14
try this: 

@Component
@Slf4j
public class CustomWebFilter implements WebFilter, Ordered {
    @Value("${ss.apigateway.context.path}")
    private String contextPath;

    @Override
    public Mono<Void> filter(ServerWebExchange serverWebExchange,
                             WebFilterChain webFilterChain) {
        String path = serverWebExchange.getRequest().getURI().getPath().
                replace(contextPath, "");

        log.debug("Old Path: '{}', Modified Path: '{}'",
                serverWebExchange.getRequest().getURI().getPath(), path);

        ServerHttpRequest updatedHttpRequest = serverWebExchange.getRequest().mutate().path(path).build();
        return webFilterChain.filter(serverWebExchange.mutate().request(updatedHttpRequest).build());
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}
濮阳烨然
2023-03-14

您可以使用@order注释来提到筛选器的顺序

 类似资料:
  • 我们正在用Spring云构建一个基于微服务的系统,我们使用Zuul作为边缘服务器和一些后端微服务。在其中一个后端服务中,我们使用Redis来管理,并存储一些与用户相关的对象。 直接访问微服务时一切正常,但通过Zuul访问时出错,因为备份微服务总是获得一个新的ID。我尝试使用和将cookie转发给使用的微服务,但微服务最终没有使用cookie值在Redis中创建spring:sessions。 任何

  • sessionStorage 会话存储 存储针对QQ帐号隔离 数据存储于内存中,当前游戏结束后被清空 函数 key( index ) 获取对应索引的key 手q 版本7.8.5 参数 参数名 类型 说明 index number 索引值 返回值 类型 说明 string 说明 示例 var stringKey = BK.sessionStorage.key(0); getItem( key )

  • 在我的REST controllers Spring项目中,我想在Redis中存储会话信息。 在我的Application.Properties中,我定义了以下内容: 我还启用了Http Redis会话: 我终于有了一个这样的redis连接工厂: \xac\xx\x00\x05sr\x00\x0ejava.lang.long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x0

  • 问题内容: 我正在尝试将Redis会话集成到用Node.js编写的身份验证系统中。 我已经能够成功设置Redis服务器和Express服务器。 这是我的设置(只是重要的一点): 现在…我该如何实际创建,阅读和销毁会话?我已经阅读了很多关于如何设置的文章以及关于SO的许多问题,但是我发誓每个都只停留在配置上,并且不解释如何实际使用它… 我知道这可能非常简单,但是请不要投票,而只是解释一下:)。 问题

  • 问题内容: 我正在尝试在我的Express应用程序中使用redis进行会话。 我执行以下操作: 稍后,在我的应用程序中,如果执行以下操作: 我得到: 无法读取未定义的属性“ someProperty” 这表明req.session是未定义的 (我可以从config部分的console.log条目中看到) 我肯定有redis运行,并且可以看到我的应用最初连接到它(使用redis-cli监视器) 问题

  • 问题内容: 我目前正在使用MySql来存储我的会话。效果很好,但是有点慢。 我曾经被要求使用Redis,但是我想知道这是否是一个好主意,因为我听说Redis会延迟写入操作。我有点害怕,因为会话需要是实时的。 有没有人遇到过这样的问题? 问题答案: Redis非常适合存储会话。所有操作都在内存中执行,因此读和写将很快。 第二个方面是会话状态的持久性。Redis使您可以灵活地将会话状态持久化到硬盘。您