微服务---API网关服务Gateway

文章目录

      • 一、简介
        • 1.为什么我们要使用API网关服务
        • 2.SpringCloudGateway与Zuul 1.x的区别
      • 二、基本概念
        • 1.路由(Route)
        • 2.断言(Predicate)
        • 3.过滤器(Filter)
      • 三、简单使用
        • 1.两种方式的路由配置
          • 方法一:在yml中进行路由配置
          • 方法二:通过编码配置
        • 2.动态路由配置
        • 3.自定义过滤器

一、简介

Spring cloud gateway是spring官方基于Spring 5.0、Spring Boot2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供简单、有效和统一的API路由管理方式,Spring Cloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Netflix Zuul,其不仅提供统一的路由方式,并且还基于Filer链的方式提供了网关基本的功能,例如:安全、监控/埋点、限流等。
由于Zuul 1.x版本的停止维护,Spring Cloud Gateway是替代Zuul的最佳方案。
微服务---API网关服务Gateway_第1张图片

1.为什么我们要使用API网关服务

运维人员: 我们之前通过Ngnix使用路由转发,需要手动的维护转发的实例和路由规则,如增加机器,减少机器都需要人员手动的在Ngnix的配置文件中手动修改。但我们服务的实例比较多后,很明显是很不方便的。
开发人员: 我们针对每一个服务的端口都有一套校验的规则。但是在微服务中,我们拆分应用为多个服务,占据多个端口,如果没有一套统一的管理,是很麻烦的事情。

2.SpringCloudGateway与Zuul 1.x的区别

Zuul 1.x:构建于 Servlet 2.5,兼容 3.x,使用的是阻塞式的 API,不支持长连接.
Gateway: 构建于 Spring 5+,基于 Spring Boot 2.x 响应式的、非阻塞式的 API。支持 websockets,和Spring 框架紧密集成。底层使用netty模型,性能极高。

二、基本概念

服务网关的核心思想是:路由转发和执行过滤链,而SpringCloudGateWay中主要有三个核心的概念

1.路由(Route)

路由是网关最基础的部分,路由信息有一个ID、一个目的URL、一组断言和一组Filter组成。如果断言路由为真,则说明请求的URL和配置匹配

2.断言(Predicate)

Spring Cloud Gateway中的断言函数输入类型是Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的断言函数允许开发者去定义匹配来自于http request中的任何信息。目前SpringCloud Gateway支持多种方式,常见如:Path、Query、Method、Header等。
微服务---API网关服务Gateway_第2张图片
我们经常的使用的是Path来对路径进行匹配,但我们还可以使用例如After:xxxTime,代表xxx时间后该路径才能生效.

3.过滤器(Filter)

一个标准的Spring webFilter。Spring cloud gateway中的filter分为两种类型的Filter,分别是Gateway Filter和Global Filter。过滤器Filter将会对请求和响应进行修改处理.
微服务---API网关服务Gateway_第3张图片
如上图所示,Spring cloudGateway发出请求。然后再由Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway web handler。Handler再通过指定的过滤器链将请求发送到我们实际的服务执行业务逻辑,然后返回。

三、简单使用

1.两种方式的路由配置

导入依赖

      <dependency>
          <groupId>org.springframework.cloudgroupId>
          <artifactId>spring-cloud-starter-gatewayartifactId>
      dependency>
方法一:在yml中进行路由配置
  cloud:
   gateway:
     routes:
         - id: route1   #路由Id,没有固定要求但要求唯一
           uri: http://localhost:8081 #匹配提供服务的路由地址
           predicates:
                  Path=/payment/get/** #断言,路径相匹配后提供路由
         - id: route2   #路由Id,没有固定要求但要求唯一
           uri: http://localhost:8081 #匹配提供服务的路由地址
           predicates:
                  Path=/payment/do/** #断言,路径相匹配后提供路由

很明显,这里两个方法进行了路由的映射。我们之前访问的是http://localhost:8081/payment/get/1l而现在我们访问的是http://localhost:9002/payment/get/1l微服务---API网关服务Gateway_第4张图片

方法二:通过编码配置

类似于yml配置,我们将localhost:9002/baidu映射到了www.baidu.com

/**
 1. 通过编码配置Gateway路由
 */
@Configuration
public class GatewayConfig {
     
    @Bean
    public RouteLocator getCustomRouteLocator(RouteLocatorBuilder builder) {
     
        RouteLocatorBuilder.Builder routes = builder.routes();
        routes.route("route3",
                r -> r.path("/baidu")
                        .uri("https://www.baidu.com/"))
                .build();
        return routes.build();
    }
}

2.动态路由配置

当之前的8081服务是集群的时候(如有80818082构成集群)时,我们则需要开启动态路由.

  1. 开启动态路由功能
  2. uri调用时不再为固定地址,而是通过lb:服务名进行调用
cloud:
    gateway:
      routes:
          - id: route1   #路由Id,没有固定要求但要求唯一
            #uri: http://localhost:8081 #匹配提供服务的路由地址
            uri: lb://cloud-payment-service
            predicates:
                   Path=/payment/get/** #断言,路径相匹配后提供路由
          - id: route2   #路由Id,没有固定要求但要求唯一
            uri: http://localhost:8081 #匹配提供服务的路由地址
            predicates:
                   Path=/payment/do/** #断言,路径相匹配后提供路由
      discovery:
        locator:
          enabled: true  #开启从注册中心创建动态路由的功能,利用微服务名进行路由

3.自定义过滤器

实现GlobalFilterOrdered接口并重写方法.

@Component
@Slf4j
public class MyGateWayFilter implements GlobalFilter, Ordered {
     
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
     
        String name = exchange.getRequest().getQueryParams().getFirst("name");
        if (name == null) {
     
            log.info("用户名为空");
            exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    //优先级
    @Override
    public int getOrder() {
     
        return 0;
    }
}

很明显,我们自定义的filter访问时需要带上不为空的name参数.
微服务---API网关服务Gateway_第5张图片
微服务---API网关服务Gateway_第6张图片
相关源码:https://github.com/wantao666/SpringCloud2020

你可能感兴趣的:(微服务,gateway,springcloud,微服务,java,网关)