其他分享
首页 > 其他分享> > SpringCloud Gateway路由网关的使用介绍

SpringCloud Gateway路由网关的使用介绍

作者:互联网

概述

​ Spring Cloud Gateway是Spring官方基于Spring 5.0、Spring Boot 2.0和Project Reactor等技术开发的网关,旨在为微服务架构提供一种简单而有效的统一的API路由管理方式,统一访问接口,Spring Cloud Gateway作为Spring Cloud生态系中的网关,目标是替换Zuul,其不仅提供统一的路由方式,并基于Filter链的方式提供了网关基本的功能,例如:安全、监控\埋点、限流等。它是基于Netty的响应式开发模式

路由

2.1 核心概念

2.2 基础配置

2.2.1 搭建环境

(1)创建工程导入坐标

<!--  gateway 基于netty + webFlux实现;webFlux与Springmvc存在冲突-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

(2)配置启动类

@SpringBootApplication
public class ShopGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(ShopGatewayApplication.class, args);
    }

}

(3)编写配置文件

server:
  port: 8089

spring:
  application:
    name: api-gateway
  #配置gateway的路由
  cloud:
    gateway:
      routes:
      #路由ID\URI\断言
      - id: product-api
        uri: http://127.0.0.1:9001
        predicates:
        - Path=/product/**

2.2.2 路由规则(断言|路由条件)

predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
predicates:
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
predicates:
- Cookie=chocolate, ch.p
predicates:
- Header=X-Request-Id, \d+
predicates:
- Host=**.somehost.org,**.anotherhost.org
predicates:
- Method=GET # 所有GET请求都将被路由
predicates:
# segment为Map类型变量
- Path=/foo/{segment},/bar/{segment}
# 也可以直接写出 **代表所有请求都通过
- Path=/consumer/**
predicates:
- Query=baz
predicates:
- Query=foo, ba.

2.2.3 动态路由(面向服务的路由)

<!-- eureka -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
@EnableEurekaClient //可以省略
@SpringBootApplication
public class ShopGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(ShopGatewayApplication.class, args);
    }

}
spring:
  application:
    name: shop-gateway-server
  #配置gateway的路由
  cloud:
    gateway:
      routes:
      #路由ID\URI\断言
      - id: product-api
        #uri: http://127.0.0.1:9001 #不使用注册中心
        uri: lb://shop-product-server #使用注册中心;格式需满足 lb:// 注册中心获取微服务的名称
        predicates:
        - Path=/product/**

#eureka注册中心配置
eureka:
  client:
    service-url:
      defaultZone: http://localhost:10000/eureka/
  instance:
    prefer-ip-address: true #使用IP地址注册

2.2.4 重写转发路径(filters过滤器)

spring:
  application:
    name: shop-gateway-server
  #配置gateway的路由
  cloud:
    gateway:
      routes:
      #路由ID\URI\断言
      - id: product-api
        #uri: http://127.0.0.1:9001 #不使用注册中心
        uri: lb://shop-product-server #使用注册中心;格式需满足 lb:// 注册中心获取微服务的名称
        predicates:
        - Path=/product-service/product/**
        filters: #配置过滤器,实现路径重写转发
        - RewritePath=/product-service/(?<segment>.*),/$\$(segment) #路径重写过滤器

2.2.5 微服务名称转发

spring:
  application:
    name: shop-gateway-server
  #配置gateway的路由
  cloud:
    gateway:
      routes:
      #路由ID\URI\断言
      - id: product-api
        #uri: http://127.0.0.1:9001 #不使用注册中心
        uri: lb://shop-product-server #使用注册中心;格式需满足 lb:// 注册中心获取微服务的名称
        predicates:
        - Path=/product-service/product/**
        filters: #配置过滤器,实现路径重写转发
        - RewritePath=/product-service/(?<segment>.*),/$\$(segment) #路径重写过滤器
      #自动从注册中心获取服务 http://localhost:8089/shop-product-server/product/query
      discovery:
        locator:
          enabled: true #开启根据服务名称自动转发
          lower-case-service-id: true #微服务名称以小写呈现

过滤器

3.1 过滤器的生命周期

3.2 过滤器的类型

网关限流

4.1 常见的限流算法

4.2 Filter限流

Spring Cloud Gateway官方提供了基于令牌桶的限流支持,基于其内置的过滤器工厂RequestRateLimiterGatewayFilterFactory实现,在过滤器工厂中是通过Redis和Lua脚本结合的方式进行流量控制。

(1)环境搭建

(2)修改配置文件

spring:
  application:
    name: shop-gateway-server
  #配置Redis
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456
    database: 0
  #配置gateway的路由
  cloud:
    gateway:
      routes:
        #路由ID\URI\断言
        - id: product-api
          #uri: http://127.0.0.1:9001 #不使用注册中心
          uri: lb://shop-product-server #使用注册中心;格式需满足 lb:// 注册中心获取微服务的名称
          predicates:
            - Path=/product-service/**
          filters: #配置过滤器,实现路径重写转发
            - RewritePath=/product-service/(?<segment>.*), /$\{segment} #路径重写过滤器
            #配置限流
            - name: RequestRateLimiter
              args:
                key-resolver: '#{@myKeyResolver}' #使用SpEL从容器获取对象
                redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率
                redis-rate-limiter.burstCapacity: 3 #令牌桶上限

(3)编写自定义KeyResolver

/**
 * @Description 基于请求路径限流
 *  基于请求路径: /abc
 *  基于请求IP: 127.0.0.1
 *  基于参数:
 */
@Configuration
public class MyKeyResolverConfig {

    @Bean
    public KeyResolver myKeyResolver(){
        //实现基于请求路径自定义的KeyResolver
        return exchange -> Mono.just(exchange.getRequest().getPath().toString());
    }

    @Bean
    public KeyResolver ipKeyResolver(){
        //实现基于请求ip自定义的KeyResolver
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostString());
    }

    @Bean
    public KeyResolver paramKeyResolver(){
        //实现基于请求参数自定义的KeyResolver
        return exchange -> Mono.just(exchange.getRequest().getQueryParams().toString());
    }

}

4.3 Sentinel限流

4.3.1 Sentinel限流实现

Sentinel支持对Gateway|Zuul等主流API网关的限流,其提供了两种资源维度的限流。

Sentinel(1.6.0+)提供了网关限流规则和自定义API的实体和管理逻辑

(1)环境搭建

<!-- 集成Sentinel实现Sentinel限流 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
    <version>1.8.1</version>
</dependency>
@Configuration
public class MySentinelConfig {

    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public MySentinelConfig(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler(){
        return new SentinelGatewayBlockExceptionHandler(viewResolvers,serverCodecConfigurer);
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter(){
        return new SentinelGatewayFilter();
    }

    @PostConstruct
    private void initGatewayRules(){
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(new GatewayFlowRule("product-api") //资源名称,这里为路由router的ID
                //路由模式
                .setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_ROUTE_ID)
                .setCount(1) //QPS即每秒钟允许的调用次数
                .setIntervalSec(1)); //每隔多少时间统计一次汇总数据
        GatewayRuleManager.loadRules(rules);
    }

}

4.3.2 自定义异常提示

@PostConstruct
public void initBlockHandlers(){
    //声明自定义异常信息
    BlockRequestHandler handler = new BlockRequestHandler() {
        @Override
        public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
            Map<String,String> result = new HashMap<>();
            result.put("code","403");
            result.put("message","对不起,请稍后再试");
            return ServerResponse.status(HttpStatus.OK)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .body(BodyInserters.fromObject(result));
        }
    };
    GatewayCallbackManager.setBlockHandler(handler); //设置自定义异常信息
}

4.3.3 自定义分组限流

 @PostConstruct
private void initGatewayRules(){
    Set<GatewayFlowRule> rules = new HashSet<>();
    //配置分组限流
    rules.add(new GatewayFlowRule("product-api") //分组名称
              .setCount(1) //QPS即每秒钟允许的调用次数
              .setIntervalSec(1)); //每隔多少时间统计一次汇总数据
    rules.add(new GatewayFlowRule("order-api") //分组名称
              .setCount(1) //QPS即每秒钟允许的调用次数
              .setIntervalSec(1)); //每隔多少时间统计一次汇总数据
    GatewayRuleManager.loadRules(rules);
}

//自定义分组限流,基于API
@PostConstruct
private void initCustomizedApis(){
    Set<ApiDefinition> apiDefinitions = new HashSet<>();
    ApiDefinition api1 = new ApiDefinition("product-api") //分组名称
        .setPredicateItems(new HashSet<ApiPredicateItem>(){{
            add(new ApiPathPredicateItem()
                .setPattern("/product-service/product/**")); //配置匹配的连接API(模糊匹配)
        }});
    ApiDefinition api2 = new ApiDefinition("order-api")
        .setPredicateItems(new HashSet<ApiPredicateItem>(){{
            add(new ApiPathPredicateItem()
                .setPattern("/product-service/order")); //配置匹配的连接API(完全匹配)
        }});
    apiDefinitions.add(api1);
    apiDefinitions.add(api2);
    GatewayApiDefinitionManager.loadApiDefinitions(apiDefinitions);
}

高可用

5.1 概述

该可用HA是分布式系统架构设计中必须考虑的因素之一,它通常指,通过设计减少系统不能提供服务的时间。众所周知,单点是系统高可用的大敌,单点往往是系统高可用最大的风险和敌人,应该尽量在设计系统的过程中避免单点,方法论上,高可用保证的原则是“集群化”,或者交“冗余”,只有一个单点,挂了服务会受影响,如果有冗余备份,挂了还有其他backup能够顶上。
在这里插入图片描述

5.2 结合Nginx实现网关的高可用

标签:product,http,SpringCloud,网关,uri,限流,predicates,Gateway,路由
来源: https://blog.csdn.net/fuu123f/article/details/118489795