Gateway网关实战

目录

什么是API网关?

网关为什么出现?

什么是Spring Cloud Gateway?

核心概念

Spring Cloud Gateway实战

路由断言工厂(Route Predicate Factories)配置

路径匹配

Header匹配

过滤器工厂( GatewayFilter Factories)配置

添加请求头

添加请求参数

自定义过滤器工厂

全局过滤器(Global Filters)配置

LoadBalancerClientFilter

自定义全局过滤器

Gateway跨域配置(CORS Configuration)

Gateway基于redis+lua脚本限流

Gateway整合sentinel限流


什么是API网关?

        API网关是随着微服务概念兴起的一种架构模式,它是运行于外部请求与内部服务之间的一个流量入口,用于实现对外部请求的协议转换、鉴权、流控、参数校验、监控等通用功能。

网关为什么出现?

       在微服务架构中,通常一个系统会被拆分为多个微服务,如果根据每个微服务的地址发起调用,存在如下问题:

  • 客户端多次请求不同的微服务,会增加客户端代码和配置的复杂性,维护成本比价高
  • 认证复杂,每个微服务可能存在不同的认证方式,客户端去调用,要去适配不同的认证
  • 存在跨域的请求,调用链有一定的相对复杂性(防火墙 / 浏览器不友好的协议)
  • 难以重构,随着项目的迭代,可能需要重新划分微服务

       为了解决上面的问题,微服务引入了 API网关 的概念,API网关为微服务架构的系统提供简单、有效且统一的API路由管理,作为系统的统一入口,提供内部服务的路由中转,给客户端提供统一的服务,可以实现一些和业务没有耦合的公用逻辑,主要功能包含认证、鉴权、路由转发、安全策略、防刷、流量控制、监控日志等。


什么是Spring Cloud Gateway?

       Spring Cloud Gateway 是Spring Cloud官方推出的第二代网关框架,定位于取代 Netflix Zuul。Spring Cloud Gateway 旨在为微服务架构提供一种简单且有效的 API 路由的管理方式,并基于 Filter 的方式提供网关的基本功能,例如说安全认证、监控、限流等等。

        Spring Cloud Gateway 是由 WebFlux + Netty + Reactor 实现的响应式的 API 网关。它不能在传统的 servlet 容器中工作,也不能构建成 war 包。

           

核心概念

路由(route)

        路由是网关中最基础的部分,路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。

断言(predicates)

       Java8中的断言函数,SpringCloud Gateway中的断言函数类型是Spring5.0框架中的ServerWebExchange。断言函数允许开发者去定义匹配Http request中的任何信息,比如请求头和参数等。如果断言为真,则说明请求的URL和配置的路由匹配。

过滤器(Filter)

       SpringCloud Gateway中的filter分为Gateway FilIer和Global Filter。Filter可以对请求和响应进行处理。


Spring Cloud Gateway实战

1) 引入依赖

<!-- gateway网关 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<!-- nacos服务注册与发现 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

注意:会和spring-webmvc的依赖冲突,需要排除spring-webmvc

2) 编写yml配置文件

spring:
  application:
    name: mall-gateway
  #配置nacos注册中心地址
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

    gateway:
      #设置路由:路由id、路由到微服务的uri、断言
      routes:
        - id: order_route  #路由ID,全局唯一,建议配置服务名
          uri: lb://mall-order  #lb 整合负载均衡器ribbon,loadbalancer
          predicates:
            - Path=/order/**   # 断言,路径相匹配的进行路由

        - id: user_route   #路由ID,全局唯一,建议配置服务名
          uri: lb://mall-user  #lb 整合负载均衡器ribbon,loadbalancer
          predicates:
            - Path=/user/**   # 断言,路径相匹配的进行路由

路由断言工厂(Route Predicate Factories)配置

       predicates:路由断言,判断请求是否符合要求,符合则转发到路由目的地。application.yml配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件。

通过网关启动日志,可以查看内置路由断言工厂:

路径匹配
spring:
  cloud:
    gateway:
      #设置路由:路由id、路由到微服务的uri、断言
      routes:
      - id: order_route  #路由ID,全局唯一
        uri: lb://mall-order  #目标微服务的请求地址和端口
        predicates:
         # 测试:http://localhost:8888/order/findOrderByUserId/1
        - Path=/order/**    # 断言,路径相匹配的进行路由
Header匹配
spring:
  cloud:
    gateway:
      #设置路由:路由id、路由到微服务的uri、断言
      routes:
      - id: order_route  #路由ID,全局唯一
        uri: lb://mall-order  #目标微服务的请求地址和端口
        predicates:
          - Path=/order/**   # 断言,路径相匹配的进行路由
         # Header匹配  请求中带有请求头名为 x-request-id,其值与 \d+ 正则表达式匹配
         - Header=X-Request-Id, \d+

过滤器工厂( GatewayFilter Factories)配置

GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理。

添加请求头

需求:给所有进入mall-order的请求添加一个请求头:X-Request-color=red。

只需要修改gateway服务的application.yml文件,添加路由过滤即可:

spring:
  cloud:
    gateway:
      #设置路由:路由id、路由到微服务的uri、断言
      routes:
      - id: order_route  #路由ID,全局唯一
        uri: http://localhost:8020  #目标微服务的请求地址和端口
        #配置过滤器工厂
        filters:
        - AddRequestHeader=X-Request-color, red  #添加请求头

测试http://localhost:8888/order/testgateway

@GetMapping("/testgateway")
public String testGateway(HttpServletRequest request) throws Exception {
    log.info("gateWay获取请求头X-Request-color:"
            +request.getHeader("X-Request-color"));
    return "success";
}
@GetMapping("/testgateway2")
public String testGateway(@RequestHeader("X-Request-color") String color) throws Exception {
    log.info("gateWay获取请求头X-Request-color:"+color);
    return "success";
}

添加请求参数
spring:
  cloud:
    gateway:
      #设置路由:路由id、路由到微服务的uri、断言
      routes:
      - id: order_route  #路由ID,全局唯一
        uri: http://localhost:8020  #目标微服务的请求地址和端口
        #配置过滤器工厂
        filters:
        - AddRequestParameter=color, blue  # 添加请求参数

测试http://localhost:8888/order/testgateway3

@GetMapping("/testgateway3")
public String testGateway3(@RequestParam("color") String color) throws Exception {
    log.info("gateWay获取请求参数color:"+color);
    return "success";
}


自定义过滤器工厂

        继承AbstractNameValueGatewayFilterFactory且我们的自定义名称必须要以GatewayFilterFactory结尾并交给spring管理。

@Component
@Slf4j
public class CheckAuthGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {

    @Override
    public GatewayFilter apply(NameValueConfig config) {
        return (exchange, chain) -> {
            log.info("调用CheckAuthGatewayFilterFactory==="
                    + config.getName() + ":" + config.getValue());
            return chain.filter(exchange);
        };
    }
}

配置自定义的过滤器工厂

spring:
  cloud:
    gateway:
      #设置路由:路由id、路由到微服务的uri、断言
      routes:
      - id: order_route  #路由ID,全局唯一
        uri: http://localhost:8020  #目标微服务的请求地址和端口
        #配置过滤器工厂
        filters:
        - CheckAuth=zhangsan,男   #自定义过滤器工厂

全局过滤器(Global Filters)配置

全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。

  • GatewayFilter:网关过滤器,需要通过spring.cloud.routes.filters配置在具体的路由下,只作用在当前特定路由上,也可以通过配置spring.cloud.default-filters让它作用于全局路由上。
  • GlobalFilter:全局过滤器,不需要再配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain能够识别的过滤器。


LoadBalancerClientFilter

其实就是用来整合负载均衡器Ribbon的

spring:
  cloud:
    gateway:
      routes:
      - id: order_route
        uri: lb://mall-order
        predicates:
        - Path=/order/**

自定义全局过滤器

         自定义全局过滤器定义方式是实现GlobalFilter接口。每一个过滤器都必须指定一个int类型的order值,order值越小,过滤器优先级越高,执行顺序越靠前。GlobalFilter通过实现Ordered接口来指定order值。

@Component
@Slf4j
public class CheckAuthFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取token
        String token = exchange.getRequest().getHeaders().getFirst("token");
        if (null == token) {
            log.info("token is null");
            ServerHttpResponse response = exchange.getResponse();
            response.getHeaders().add("Content-Type",
                    "application/json;charset=UTF-8");
            // 401 用户没有访问权限
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            byte[] bytes = HttpStatus.UNAUTHORIZED.getReasonPhrase().getBytes();
            DataBuffer buffer = response.bufferFactory().wrap(bytes);
            // 请求结束,不继续向下请求
            return response.writeWith(Mono.just(buffer));
        }
        //TODO 校验token进行身份认证
        log.info("校验token");
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 2;
    }
}

Gateway跨域配置(CORS Configuration)

在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制。

如何解决gateway跨域问题?

通过yml配置的方式

spring:
  cloud:
    gateway:
    globalcors:
      cors-configurations:
        '[/**]':
          allowedOrigins: "*"
          allowedMethods:
          - GET
          - POST
          - DELETE
          - PUT
          - OPTION

通过java配置的方式

@Configuration
public class CorsConfig {
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedMethod("*");
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }
}

Gateway基于redis+lua脚本限流

        spring cloud alibaba官方提供了RequestRateLimiter过滤器工厂,基于redis+lua脚本方式采用令牌桶算法实现了限流。

              

1)添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

2)修改 application.yml ,添加redis配置和RequestRateLimiter过滤器工厂配置

spring:
  application:
    name: mall-gateway

  redis:
    host: localhost
    port: 6379
    database: 0
    timeout: 5000
    lettuce:
      pool:
        max-active: 200
        max-wait: 10000
        max-idle: 100
        min-idle: 10
  #配置nacos注册中心地址
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

    gateway:
      #设置路由:路由id、路由到微服务的uri、断言
      routes:
        - id: order_route  #路由ID,全局唯一,建议配置服务名
          # 测试 http://localhost:8888/order/findOrderByUserId/1
          uri: lb://mall-order  #lb 整合负载均衡器ribbon,loadbalancer
          predicates:
            - Path=/order/**   # 断言,路径相匹配的进行路由
          #配置过滤器工厂
          filters:
            - name: RequestRateLimiter   #限流过滤器
              args:
                redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充速率
                redis-rate-limiter.burstCapacity: 2 #令牌桶的总容量
                key-resolver: "#{@keyResolver}" #使用SpEL表达式,从Spring容器中获取Bean对象 

3) 配置keyResolver,可以指定限流策略,比如url限流,参数限流,ip限流等

@Bean
KeyResolver keyResolver() {
    //url限流
    return exchange -> Mono.just(exchange.getRequest().getURI().getPath());
    //参数限流
    //return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}

Gateway整合sentinel限流

1)引入依赖

<!-- gateway接入sentinel  -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<--sentinel规则持久化到nacos-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

2)添加yml配置,接入sentinel dashboard,通过sentinel控制台配置网关流控规则

server:
  port: 8888
spring:
  application:
    name: mall-gateway-sentinel-demo
  main:
    allow-bean-definition-overriding: true
  #配置nacos注册中心地址
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

    sentinel:
      transport:
        # 添加sentinel的控制台地址
        dashboard: 127.0.0.1:8080
      datasource:
        gateway-flow-rules:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: ${spring.application.name}-gateway-flow-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: gw-flow
        gateway-api-rules:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: ${spring.application.name}-gateway-api-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: gw-api-group
        degrade-rules:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: ${spring.application.name}-degrade-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: degrade
        system-rules:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: ${spring.application.name}-system-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: system

    gateway:
      #设置路由:路由id、路由到微服务的uri、断言
      routes:
      - id: order_route  #路由ID,全局唯一,建议配合服务名
        uri: lb://mall-order  #lb 整合负载均衡器ribbon,loadbalancer
        predicates:
        - Path=/order/**

      - id: user_route
        uri: lb://mall-user  #lb 整合负载均衡器ribbon,loadbalancer
        predicates:
        - Path=/user/**
  • 28
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
关于Spring Cloud Gateway实战,有很多方面可以探索和实践。以下是一些常见的实战主题和示例: 1. 路由配置:使用Spring Cloud Gateway进行路由配置,将请求转发到不同的后端服务。可以通过YAML或Java代码方式进行配置,并可以使用各种条件和断言来实现动态路由。 2. 过滤器:利用Spring Cloud Gateway的过滤器功能,对请求进行预处理或后处理。常见的过滤器包括鉴权、请求转发修改、请求日志记录等。 3. 限流和熔断:使用Spring Cloud Gateway的限流和熔断功能,保护后端服务免受过载和故障的影响。可以使用内置的限流和熔断策略,或者集成第三方限流和熔断组件。 4. 请求重试:在网络不稳定的情况下,使用Spring Cloud Gateway的请求重试功能,自动重新发送请求,提高系统的可靠性和容错性。 5. 跨域支持:通过Spring Cloud Gateway配置跨域资源共享(CORS),允许跨域访问资源,提高前后端分离架构的灵活性。 6. 动态路由:结合服务注册中心(如Eureka或Consul)和配置中心(如Spring Cloud Config),实现动态路由的管理和配置。 7. 监控和日志:使用Spring Cloud Gateway的监控和日志功能,对请求进行统计和分析,了解系统的性能和健康状况。 以上只是一些常见的实战主题,实际上Spring Cloud Gateway还有更多功能和扩展性可供实践。你可以根据自己的需求和场景,选择适合的实战方向,深入学习和应用Spring Cloud Gateway

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值