微服务架构——路由网关Spring Cloud Gateway

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取 2000+ 道 Java 面试题

一、概述

1.关于Spring Cloud Finchley

Spring Cloud Finchley是6月19日Spring官方正式发布GA版本,Finchley.Release支持了Spring Boot2.0,要求起步JDK8,支持JDK9,Finchley版本带了新的子项目,包括对原先版本的子项目的升级,原先支持的组件现在已经全部为2.0.0.Release,并且在官方的版本生命周期公告中说明,Camden release已经到了终止状态,Dalston release将于2018年12月结束,Edgware release将遵循Spring Boot 1.5.x系列的生命周期结束。Spring Boot2.0的新特性本文不再赘述,本文主要介绍Spring Cloud新的开源子项目Spring Cloud Gateway。

2.关于Spring Cloud Gateway

Spring Cloud Gateway是由spring官方基于Spring5.0,Spring Boot2.0,Project Reactor等技术开发的网关,目的是代替原先版本中的Spring Cloud Netfilx Zuul,目前Netfilx已经开源了Zuul2.0,但Spring 没有考虑集成,而是推出了自己开发的Spring Cloud GateWay。该项目提供了一个构建在Spring Ecosystem之上的API网关,旨在提供一种简单而有效的途径来发送API,并向他们提供交叉关注点,例如:安全性,监控/指标和弹性.

二、实践

以下将介绍Spring Cloud Gateway的一些重点功能和扩展方式,关于基础使用不再文中赘述,如有需要请查阅相关文档。

1.自定义GatewayFilter

GatewayFiltery有两种类型的filter,分别为pre和post类型,以下提供一个demo的配置

定义PreGatewayFilter:

    public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory {

          public PreGatewayFilterFactory() {
              super(Config.class);
          }

          public GatewayFilter apply() {
              return apply(o -> {
              });
          }
          @Override
          public GatewayFilter apply(Config config) {
              // grab configuration from Config object
              return (exchange, chain) -> {
                  //If you want to build a "pre" filter you need to manipulate the
                  //request before calling change.filter  ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
                  builder.header("GatewayFilter", "PreGatewayFilterFactory success");
                  //use builder to manipulate the request
                  return chain.filter(exchange.mutate().request(builder.build()).build());
              };
          }
            public static class Config {
                //Put the configuration properties for your filter here
          }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

定义PostGatewayFilter:

    public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory {

        private Logger logger = LoggerFactory.getLogger(PostGatewayFilterFactory.class);

        public PostGatewayFilterFactory() {
            super(Config.class);
        }

        public GatewayFilter apply() {
            return apply(o -> {
            });
        }

        @Override
        public GatewayFilter apply(Config config) {
            return (exchange, chain) -> {
              logger.info("PostGatewayFilter...");
              return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                  ServerHttpResponse response = exchange.getResponse();
                //Manipulate the response in some way
                }));
              };
        }

        public static class Config {
            //Put the configuration properties for your filter here
      }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

自定义GatewayFilter需要在RouteLocator中配置为具体Route项加入,下文RouteLocator配置中会提供demo.

2.全局过滤器(GlobalFilter)

    @Configuration
    public class GlobalRouteFilter implements GlobalFilter {
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
            builder.header("GlobalFilter","GlobalFilter success");
            chain.filter(exchange.mutate().request(builder.build()).build());
            return chain.filter(exchange.mutate().request(builder.build()).build());
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

自定义GlobalFilter只要使用了@Configuration注解或者配置为一个spring bean就会生效,不需要在RouteLocator中配置。

3.请求限流过滤器(RequestRateLimiter)

目前限流Spring Cloud提供了redis的实现,不过可以自定义RequestRateLimiter的实现。Spring Cloud提供的redis实现基于lua加redis桶实现,需要引入Redis的依赖和Redis的相关数据源配置,Redis依赖如下:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

Redis限流有两个参数需要配置,redis-rate-limiter.replenishRate是您希望允许用户每秒处理多少个请求,而不会丢失任何请求;redis-rate-limiter.burstCapacity是用户允许在一秒钟内完成的最大请求数,这是令牌桶可以容纳的令牌的数量,将此值设置为零将阻止所有请求。

过滤器采用可选的keyResolver参数特定于限流,可选参数可以自定义设置,以下为一个根据romoteAddress的demo配置(注意需要配置为一个spring bean):

    @Configuration
    public class RequestRateLimiterConfig {
        @Bean
        public KeyResolver addressKeyResolver() {
            return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

RequestRateLimiter属于GatewayFilter Factories一种,所以需要在RouteLocator中加入为具体Route项加入或者在配置文件application.yml中配置:

如采用redis限流application.yml配置如下:

        spring:
          cloud:
            gateway:
              routes:
              - id: requestratelimiter_route
                uri: http://example.org
                filters:
                - name: RequestRateLimiter
                  args:
                    redis-rate-limiter.replenishRate: 10
                    redis-rate-limiter.burstCapacity: 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

如果自定义RequestRateLimiter的application.yml配置如下:

        spring:
          cloud:
            gateway:
              routes:
              - id: requestratelimiter_route
                uri: http://example.org
                filters:
                - name: RequestRateLimiter
                  args:
                    rate-limiter: "#{@myRateLimiter}"
                    key-resolver: "#{@userKeyResolver}"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

使用SpEL按名称引用bean。#{@ myRateLimiter}是引用名为myRateLimiter的bean的SpEL表达式。

使用RouteLocator中加入为具体Route项配置在下文RouteLocator配置中会提供demo.

4.权重路由(WeightRoutePredicateFactory)

WeightRoutePredicateFactory是一个路由断言工厂,采用分组的方式来实现权重路由,同样可以采用application.yml或者RouteLocator进行配置:

        spring:
          application:
            name: gateway
          cloud:
            gateway:
              routes:
              - id: provide1
                uri: http://localhost:8080/provide
                predicates:
                - Path=/test
                - Weight=provide, 90
              - id: provide2
                uri: http://localhost:8081/provide
                predicates:
                - Path=/test
                - Weight=provide, 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

RouteLocator配置下文中会提供demo。

5.Hystrix GatewayFilter Factory、 LoadBalancerClient Filter、DiscoveryClient Route Definition Locator的使用

Spring Cloud Gateway提供的这三个功能比较重要且基本都会用到,但比较简单放一块来说明。

Hystrix GatewayFilter Factory需要引入如下依赖:

                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
                </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

配置如下:

        hystrix:
          command:
            default:
              execution:
                isolation:
                  thread:
                    timeoutInMilliseconds: 3000
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

DiscoveryClient Route Definition Locatorr需要在启动类加上@EnableDiscoveryClient注解并在配置文件中添加eureka或其他注册中心的配置,并且加入如下配置

        spring:
          cloud:
            gateway:
              discovery:
                locator:
                  enabled: true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

eureka的依赖如下:

                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
                </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

LoadBalancerClient Filter的使用比较简单,只需在url前加上lb,以下是这三部分综合使用的一个demo

        spring:
          cloud:
            gateway:
              discovery:
                locator:
                  enabled: true
              routes:
              - id: Hystrix
                uri: lb://user
                predicates:
                - Path=/test/**
                filters:
                - name: Hystrix
                  args:
                    name: fallbackcmd
                    fallbackUri: forward:/fallback
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

其中user是一个向注册中心注册名为user的服务。

7.Websocket Routing Filter

websocket的路由也比较简单在url前加上ws,如果还要使用LoadBalancerClient Filter和DiscoveryClient Route只需 lb:ws: //serviceid 这样写url就可以。

8.RouteLocator

Spring Cloud Gateway为了在Java中进行简单的配置,在RouteLocatorBuilder bean中定义了流畅的API,以下提供与上文相关的demo配置:

        @Configuration
        public class RoutesConfig {

            @Autowired
            private KeyResolver addressKeyResolver;

            @Bean
            public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
                return builder.routes()
                        //权重路由
                        .route(r->r.weight("provide",90).and().path("/test/weight").filters(f -> f.retry(3).filter(new PreGatewayFilterFactory().apply()).filter(new PostGatewayFilterFactory().apply()).requestRateLimiter().rateLimiter(RedisRateLimiter.class,config -> config.setBurstCapacity(1).setReplenishRate(1)).configure(config -> config.setKeyResolver(addressKeyResolver)).stripPrefix(1).hystrix(config -> config.setFallbackUri("forward:/fallback").setName("fallbackcmd"))).uri("http://localhost:3001/test/weight"))
                        .route(r->r.weight("provide",5).and().path("/test/weight").filters(f -> f.retry(3).filter(new PreGatewayFilterFactory().apply()).filter(new PostGatewayFilterFactory().apply()).requestRateLimiter().rateLimiter(RedisRateLimiter.class,config -> config.setBurstCapacity(1).setReplenishRate(1)).configure(config -> config.setKeyResolver(addressKeyResolver)).stripPrefix(1).hystrix(config -> config.setFallbackUri("forward:/fallback").setName("fallbackcmd"))).uri("http://localhost:3002/test/weight"))
                        //集成了可能会用到的各种filter
                        .route(r -> r.path("/test/**").filters(f -> f.retry(3).filter(new PreGatewayFilterFactory().apply()).filter(new PostGatewayFilterFactory().apply()).requestRateLimiter().rateLimiter(RedisRateLimiter.class,config -> config.setBurstCapacity(1).setReplenishRate(1)).configure(config -> config.setKeyResolver(addressKeyResolver)).stripPrefix(1).hystrix(config -> config.setFallbackUri("forward:/fallback").setName("fallbackcmd"))).uri("lb://user"))
                        .build();
            }
        }

来源:http://ddrv.cn/a/88268

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » 微服务架构——路由网关Spring Cloud Gateway

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏