AlibabaCloud 核⼼组件网关 Gateway 实战

微服务的网关和应用场景

什么是网关?

  • API Gateway,是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能,提供路由请求、鉴权、监控、缓存、限流等功能
  • 统一接入
    • 智能路由
    • AB测试、灰度测试
    • 负载均衡、容灾处理
    • 日志埋点(类似Nignx日志)
  • 流量监控
    • 限流处理
    • 服务降级
  • 安全防护
    • 鉴权处理
    • 监控
    • 机器网络隔离

主流的网关

  • Zuul:是 Netflix 开源的微服务网关,和 Eureka、Ribbon、Hystrix 等组件配合使用,依赖组件比较多,性能较差
  • Kong:由 Mashape 公司开源的,基于 Nginx 的 API gateway
  • Nginx+Lua:是一个高性能的 HTTP 和反向代理服务器,lua 是脚本语言,让 Nginx 执行 Lua 脚本,并且高并发、非阻塞的处理各种请求
  • SpringCloud Gateway: Spring 公司专门开发的网关,替代Zuul

注意:AlibabaCloud 全家桶还没对应的网关,我们就用 SpringCloud 官方推荐的 Gateway

什么是 SpringCloud Gateway?

  • Spring 官方出品,基于 Spring5+Reactor 技术开发的网关
  • 性能强劲基于 Reactor+WebFlux、功能多样
  • 基于 SpringBoot2.x,直接可以 jar 包方式运行

官方文档:https://spring.io/projects/spring-cloud-gateway

创建 SpringCloud 网关项目

添加依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
</dependencies>

配置实战

server:
  port: 8888
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes: #数组形式
        - id: order-service  #路由唯一标识
          uri: http://127.0.0.1:8000  #想要转发到的地址
          order: 1 #优先级,数字越小优先级越高
          predicates: #断言 配置哪个路径才转发
            - Path=/order-server/**
          filters: #过滤器,请求在传递过程中通过过滤器修改
            - StripPrefix=1  #去掉第一层前缀
#访问路径 http://localhost:8888/order-server/api/v1/video_order/list
#转发路径 http://localhost:8000/order-server/api/v1/video_order/list  
#需要过滤器去掉前面第一层

存在的问题

  • 微服务地址写死
  • 负载均衡没做到

Gateway 配置 Nocas

添加 Nacos 服务治理配置

  • 网关添加 Naocs 依赖
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
  • 启动类开启支持
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}
  • 修改配置文件
server:
  port: 8888
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
​
    gateway:
      routes: #数组形式
        - id: order-service  #路由唯一标识
          #uri: http://127.0.0.1:8000  #想要转发到的地址
          uri: lb://xdclass-order-service  # 从nacos获取名称转发,lb是负载均衡轮训策略
​
          predicates: #断言 配置哪个路径才转发
            - Path=/order-server/**
          filters: #过滤器,请求在传递过程中通过过滤器修改
            - StripPrefix=1 #去掉第一层前缀
      discovery:
        locator:
          enabled: true  #开启网关拉取nacos的服务​
## 访问路径 http://localhost:8888/order-server/api/v1/video_order/list

交互流程

  • 客户端向 SpringCloud Gateway 发出请求
  • 如果网关处理程序映射确定请求与路由匹配,则将其发送到网关 Web 处理程序
  • 通过特定过滤器链运行,前置处理->后置处理

Gateway 内置的路由断言

什么是 Gateway 路由断言

  • Predicate 来源于Java8,接受输入参数,返回一个布尔值结果
  • SpringCloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则
  • 转发的判断条件,SpringCloud Gateway 支持多种方式,常见如:Path、Query、Method、Header 等
  • 支持多个 Predicate 请求的转发是必须满足所有的 Predicate 后才可以进行路由转发

内置路由断言介绍 RoutePredicateFactory 接口实现类

参数编写规则 XXXRoutePredicateFactory,使用XXX作为参数配置, 例如下面

predicates:
  - Host=
  - Path=
  - Method=
  - Header=
  - Query=
  - Cookie=

Gateway 路由接口定时下线实战

需求:接口需要在指定时间进行下线,过后不可以在被访问

  • 使用 Before,只要当前时间小于设定时间,路由才会匹配请求
  • 东8区的 2020-09-11T01:01:01.000+08:00 后,请求不可访问
  • 为了方便测试,修改时间即可
predicates:
  - Before=2020-09-09T01:01:01.000+08:00

Gateway 过滤器

过滤器生命周期

  • PRE: 这种过滤器在请求被路由之前调用,一般用于鉴权、限流等
  • POST:这种过滤器在路由到微服务以后执行,一般用于修改响应结果,比如增加header信息、打点结果日志

网关过滤器分类

  • 局部过滤器 GatewayFilter:应用在某个路由上,每个过滤器工厂都对应一个实现类,并且这些类的名称必须以 GatewayFilterFactory 结尾
  • 全局过滤器:作用全部路由上

内置很多局部过滤器,顶级接口 GatewayFilterFactory

内置很多全局过滤器,顶级接口 GlobalFilter

Gateway 全局过滤器实现用户鉴权

自定义全局过滤器实现鉴权

@Component
public class UserGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("token");
        System.out.println(token);
        if (StringUtils.isBlank(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        //继续往下执行
        return chain.filter(exchange);
    }

    //数字越小,优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}

注意:网关不要加太多业务逻辑,否则会影响性能,务必记住

posted @ 2020-11-13 09:40  认真对待世界的小白  阅读(587)  评论(0)    收藏  举报