刚接触到 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相关的组件感觉还是没有完全成熟,使用的时候可能还是会遇到比较多的坑。