微服务 SpringCloud Gateway服务网关

本文详细介绍SpringCloud Gateway的服务网关功能,包括其定义、使用场景、架构及与Zuul的区别。涵盖核心概念如路由、断言和过滤器,并提供配置方式、使用案例等实战指南。

1. gateway概述

1.1 gateway定义

SpringCloud Gateway是SpringCloud 的一个全新的项目,基于Spring5.0+SpringBoot2.0和Project Reactor等技术开发的第二代为服务网关,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。
SpringCloud Gateway作为SpringCloud 生态系统中的网关,目标是代替Zuul,在SpringCloud 2.0以上版本中,没有对新版本的Zuul2.0以上最新高性能版本进行集成,仍然还是使用的Zuul1.x非Reactor模式的老版本。二为了提升网关性能,SpringCloud Gateway是基于WebFlux框架实现的,二WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。
SpringCloud Gateway的目标是提供统一的路由方式且基于Filter链的方式提供了网关基本的功能,例如:安全,监控,指标,限流等功能。

官网地址:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/
在这里插入图片描述
Spring Cloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。
在这里插入图片描述

1.2 gateway使用场景

反向代理
鉴权
流量控制
熔断
日志监控
… …

1.3 gateway架构

在这里插入图片描述

1.4 zuul与gateway区别

在这里插入图片描述

1.5 gateway特性

在这里插入图片描述
在这里插入图片描述

2. gateway核心概念

服务网关三大核心概念
Route(路由):路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由。

Predicate(断言):参考的是java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由。

Filter(过滤):指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

在这里插入图片描述

3. gateway工作流程

官网gateway工作流程。
在这里插入图片描述

gateway核心逻辑:路由转发+执行过滤器链

4. gateway配置方式

gateWay配置的两种方式:1.yml文件,2.配置类

4.1 yml配置断言路由(推荐,简单明了)

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
            #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]
            #- Cookie=username,zzyy
            #- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式

4.2 配置类配置断言路由


/**
 * springcloud gateway配置类
 *
 * @author zrj
 * @date 2021/2/2
 * @since V1.0
 **/
@Configuration
public class GatewayConfig {
    /**
     * 配置相当于在yml中配置了一个id为path_route_hello的路由规则
     * 当访问地址http://localhost:9527/guonei的时候,gateway会通过断言是否为true
     * 匹配到对应的URI地址:http://news.baidu.com/guonei
     *
     * @param routeLocatorBuilder
     * @return
     */
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route( "path_route_hello",
                r -> r.path( "/guonei" )
                        .uri( "http://news.baidu.com/guonei" ) ).build();

        return routes.build();
    }
}

5. gateway Predicate使用

5.1 Route Predicate Factories

Route Predicate Factories:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories
在这里插入图片描述

5.2 gateway Route Predicate

在这里插入图片描述

具体参考1中的官网案例
1.After Route Predicate:- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]
2.Before Route Predicate:- Before=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
3.Between Route Predicate:   - Between=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] ,  2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
4. Cookie Route Predicate:- Cookie=username,zzyy
5. Header Route Predicate:- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式
6.Host Route Predicate:- Host=**.hello.com
7.Method Route Predicate:    - Method=GET
8.Path Route Predicate:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由
9. Query Route Predicate:  - Query=username, \d+ #要有参数名称并且是正整数才能路由

6. gateway Filter使用

6.1 什么是Filter过滤器

GatewayFilter
在这里插入图片描述

6.2 Filter的生命周期与种类

在这里插入图片描述

6.3 常用的GatewayFilter

过滤器地址:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#global-filters
在这里插入图片描述

6.4 自定义过滤器

自定义过滤器通过实现接口GlobalFilter,Ordered。

implements GlobalFilter,Ordered

7. gateway案例

gateway案例git地址:https://github.com/zrj-coder/cloudboot3

7.1 maven依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloudboot3</artifactId>
        <groupId>com.hello.springcloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-gateway-gateway9527</artifactId>
    
    <dependencies>
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.hello.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--一般基础配置类-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

7.2 yml配置

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
            #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]
            #- Cookie=username,zzyy
            #- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

7.3 代码实现

GatewayApplication9527

/**
 * 网关服务启动类
 *
 * @author zrj
 * @date 2021/2/2
 * @since V1.0
 **/
@EnableEurekaClient
@SpringBootApplication
public class GatewayApplication9527 {
    public static void main(String[] args) {
        SpringApplication.run( GatewayApplication9527.class, args );
    }
}

GatewayConfig


/**
 * springcloud gateway配置类
 *
 * @author zrj
 * @date 2021/2/2
 * @since V1.0
 **/
@Configuration
public class GatewayConfig {

    /**
     * 配置相当于在yml中配置了一个id为path_route_hello的路由规则
     * 当访问地址http://localhost:9527/guonei的时候,gateway会通过断言是否为true
     * 匹配到对应的URI地址:http://news.baidu.com/guonei
     *
     * @param routeLocatorBuilder
     * @return
     */
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route( "path_route_hello",
                r -> r.path( "/guonei" )
                        .uri( "http://news.baidu.com/guonei" ) ).build();

        return routes.build();
    }
}

MyLogGatewayFilter

/**
 * 自定义过滤器
 *
 * @author zrj
 * @date 2021/2/2
 * @since V1.0
 **/
@Slf4j
@Component
public class MyLogGatewayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info( "***********come in MyLogGateWayFilter:  " + new Date() );

        String uname = exchange.getRequest().getQueryParams().getFirst( "uname" );

        if (uname == null) {
            log.info( "*******用户名为null,非法用户,o(╥﹏╥)o" );
            exchange.getResponse().setStatusCode( HttpStatus.NOT_ACCEPTABLE );
            return exchange.getResponse().setComplete();
        }

        return chain.filter( exchange );
    }

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

DateTime

/**
 * 获取当前时间,带时区
 * 用于配置断言
 *
 * @author zrj
 * @date 2021/2/2
 * @since V1.0
 **/
public class DateTime {
    public static void main(String[] args) {
        ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
        System.out.println( zbj );

        //2021-02-02T23:15:43.456+08:00[Asia/Shanghai]
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值