2020.3.22笔记——Spring Cloud gateway应用

官方文档
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.2.RELEASE/reference/html/

Spring Cloud gateway应用

在之前也介绍过,Greenwich版本时就已经停止了对spring-cloud-netflix-zuul的更新,而spring cloud官方也推荐了使用gateway来代替zuul组件。不仅如此,gateway的功能甚至比zuul的功能更加强大。

引入依赖

下面是Spring Cloud Gateway启动器的依赖

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-gatewayartifactId>
dependency>

注意事项

gateway底层通讯是基于netty,属于异步模组,所以它不能和其他一些同步库一起使用(例如Spring Data和Spring Security),下面是官网的描述。
2020.3.22笔记——Spring Cloud gateway应用_第1张图片

基本使用

如果引入了gateway依赖,但是不想使用gateway可以配置如下属性

spring.cloud.gateway.enabled=false

接着就可以像启动普通springboot项目一样启动gateway项目就可以了,创建一个springboot启动类
2020.3.22笔记——Spring Cloud gateway应用_第2张图片

断言的使用

gateway项目的主要功能还是路由,而断言的使用就是对路由的限制,满足predicates后的条件就会路由到uri后的路径

  • 满足时间条件
spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]
  • 满足cookie条件

此路由匹配具有名称为chocolate,内容为ch.p正则表达式匹配的cookie的请求就会使用路由

spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: https://example.org
        predicates:
        - Cookie=chocolate, ch.p

除此之外还有需要断言条件的类型,可以参考官网中对于断言的描述
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.2.RELEASE/reference/html/#gateway-request-predicates-factories

注意这些断言是可以存在多个条件的,下面就是同时存在时间和cookie条件,同时满足才会被路由

        predicates:
        - Cookie=chocolate, ch.p
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]

gateway也可以去路由到eureka中的微服务,前提是gateway项目也已经注册进了eureka中,这种路由方式是默认支持负载均衡的,而且默认的策略是轮询。如下图所示,在uri: lb://后面就可以填上需要路由的微服务名。

spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**
过滤器的使用

gateway中存在很多过滤器(这个过滤器顾名思义就是在请求之前需要执行的过滤器的过滤方法),我们如果需要使用则只要在配置文件中配置即可,当然如果gateway提供的过滤器还不满足我们的需求,我们还可以自己实现自定义的过滤器。

如下配置所示,下面配置的过滤器会将相匹配的请求的请求头中添加X-Request-red=blue

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        filters:
        - AddRequestHeader=X-Request-red, blue

除此之外还有许多可以配置的过滤器,具体的使用可以参考下面的官方文档
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.2.RELEASE/reference/html/#gatewayfilter-factories
2020.3.22笔记——Spring Cloud gateway应用_第3张图片

整合Hystrix

在gateway过滤器中我们可以整合Hystrix一起使用,这样就可以使用Hystrix的功能,实现服务降级、服务熔断等功能。

首先我们如果想要整合Hystrix,必须得引入Hystrix得依赖,就是spring-cloud-starter-netflix-hystrix

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
dependency>

下面将演示Hystrix过滤器简单的使用,首先有如下的配置,这里的gateway已经配置了eureka客户端,也已经注册进了eureka中,所以eureka相关的配置没有写出。

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: user
          uri: lb://SERVICE-USER
          predicates:
            - Query=name,1
            - Query=age
            - Path=/**
          filters:
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback

hystrix:
  command:
    fallbackcmd:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000

断言和微服务路由前面已经介绍了,就不再说明了,重点是下面的配置。

          filters:
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback

hystrix:
  command:
    fallbackcmd:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000

需要关注filters中args里的name和fallbackUri属性,其中name配置的我们CommandName,对应的关系如下图所示,代表的其实就是它的Hystrix配置(Hystrix配置可以参考《Hystrix断路器组件(Finchley版)》)。2020.3.22笔记——Spring Cloud gateway应用_第4张图片
至于fallbackUri则代表降级方法的路径forward:则表示项目内跳转,后面就是路径,降级方法如下
2020.3.22笔记——Spring Cloud gateway应用_第5张图片

自定义的过滤器

只需要实现GlobalFilter和Ordered就可以创建自定义的过滤器,下面是官网的描述,地址如下

https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.2.RELEASE/reference/html/#gateway-combined-global-filter-and-gatewayfilter-ordering

2020.3.22笔记——Spring Cloud gateway应用_第6张图片
这里我们通过自定义过滤器解决单点登陆的问题,拦截未登录的请求,思路简单来说就是在路由之前通过过滤器将请求拦截,然后拿到本地缓存或数据库中的cookie检验用户是否登陆,如果cookie存在则请求继续,如果不存在则拦截请求。

过滤器的具体实现如下,最后只要加上@Component注解将过滤器注入spring容器中就会生效。

@Component
public class LoginFilter implements GlobalFilter, Ordered {
    
    //判断是否携带 login cookie
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        MultiValueMap<String, HttpCookie> cookies = request.getCookies();
//        HttpCookie httpCookie = null;
        for (Map.Entry<String, List<HttpCookie>> cookie : cookies.entrySet()) {
            if (cookie.getKey().equals("login1")) {
                System.out.println(1);
                return chain.filter(exchange);
            }
        }
        System.out.println(2);
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        return response.setComplete();
    }

    @Override
    public int getOrder() {
        return -1;
    }
}
限流的使用

对于大型大型的互联网项目,限流是必不可少的,特别是微服务项目,在了解了系统的负荷之后,如果访问流量超过负荷那么将导致服务整体被压垮,为保证服务可用预防突发流量,在流量到达设置指标时允许摒弃部分以保证服务运行正常。

对于spring cloud项目,使用的是Redis RateLimiter完成的服务限流,它是基于redis和令牌桶算法实现而来的。

官网描述如下
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.2.RELEASE/reference/html/#the-redis-ratelimiter

首先需要加入spring-boot-starter-data-redis-reactive依赖

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-redis-reactiveartifactId>
dependency>

令牌桶算法的大致原理如下
2020.3.22笔记——Spring Cloud gateway应用_第7张图片
下面是简单的配置示例,首先需要配置redis,再就是配置过滤器和令牌桶,因为限流也是基于过滤器实现的

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    timeout: 5000
  application:
    name: service-gateway #此实例注册到eureka服务端的name
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: user
          uri: lb://SERVICE-USER
          predicates:
            - Query=name,1
            - Query=age
            - Path=/**
          filters:
            - name: RequestRateLimiter
              KeyResolver: userKey
              args:
                redis-rate-limiter.replenishRate: 1
                redis-rate-limiter.burstCapacity: 2

下面就是限流的配置,也可以看作是令牌桶的配置,首先name是固定的,KeyResolver配置的是令牌的bean的name,redis-rate-limiter.replenishRate配置的是每秒钟生成的令牌数量,redis-rate-limiter.burstCapacity配置的是令牌桶的最大数量。

          filters:
            - name: RequestRateLimiter
              KeyResolver: userKey
              args:
                redis-rate-limiter.replenishRate: 1
                redis-rate-limiter.burstCapacity: 2

下面配置的就是令牌的bean对象了,具体的实现类就是KeyResolver,不过我们可以配置bean的name,上面配置的也就是bean的name。
2020.3.22笔记——Spring Cloud gateway应用_第8张图片
创建KeyResolver对象重写resolve方法,其中返回的对象就是真正的令牌,这里是将用户登陆的cookie作为令牌。这样如果用户想要访问页面就必须登陆,而且也实现了想要的限流。

@Bean
public KeyResolver userKey(){

    return new KeyResolver() {
        @Override
        public Mono<String> resolve(ServerWebExchange exchange) {
            ServerHttpRequest request = exchange.getRequest();
            HttpCookie userCookie = null;
            for (Map.Entry<String, List<HttpCookie>> cookies : request.getCookies().entrySet()) {
                if (cookies.getKey().equals("login1")) {
                    userCookie = cookies.getValue().get(0);
                }
            }
            return Mono.just(userCookie.getValue()); //
        }
    };
}

你可能感兴趣的:(微服务笔记)