Spring CLoud以Eureke为注册中心的服务搭建(七)---Gateway网关

大部分资料都来自Gateway官网 https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/

什么是Gateway

​ Spring Cloud Gateway旨在提供一种简单而有效的方法来路由到api,并为它们提供跨领域的关注点,例如:熔断、限流、重试等。

​ Spring Cloud Gateway建立在Spring Framework5、Project Reactor和SpringBoot2之上,使用非阻塞API

Gateway工作流程

Spring CLoud以Eureke为注册中心的服务搭建(七)---Gateway网关_第1张图片
​ 客户端向SpringCloudGateway发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。此处理程序通过特定于请求的筛选器链运行请求。过滤器被虚线分隔的原因是过滤器可以在发送代理请求之前和之后运行逻辑。执行所有“预”过滤逻辑。然后发出代理请求。发出代理请求后,运行“post”过滤器逻辑。

核心逻辑就是 请求转发和执行过滤器链

三大核心

Route(路由)
	路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由
Predicate(断言)
	参考的是java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
Filter(过滤)
	指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

动态代理配置 路由(Route)

新建module 命名gateway

pom

<?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>spring-cloud-eureka</artifactId>
        <groupId>com.cto</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>cloud-gateway</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <!--EurekaClient-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
    </dependencies>

    <!--
        SpringBoot的Maven插件, 能够以Maven的方式为应用提供SpringBoot的支持,可以将
        SpringBoot应用打包为可执行的jar或war文件, 然后以通常的方式运行SpringBoot应用
     -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

yml

server:
  port: 8888
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由功能
      routes:
        - id: cloud-provider
          uri: lb://cloud-provider #服务的application.name
          predicates:
            - Path=/**
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:7000/eureka/
  instance:
    hostname: cloud-gateway-service

#日志
logging:
  level:
    com:
      cto:
        cloud: debug
    org:
      springframework:
        web: info
  file: log/cloud-gateway.log

启动类

package com.cto.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * 
 * @author Zhang Wei
 * @date 2020/5/24 01:33
 * @version v1.0.1
 */
@SpringBootApplication
@EnableEurekaClient
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

依次启动 注册中心7000、gateway8888、生产者9001、生产者9002

访问:http://localhost:8888/provider/getData

Spring CLoud以Eureke为注册中心的服务搭建(七)---Gateway网关_第2张图片

Spring CLoud以Eureke为注册中心的服务搭建(七)---Gateway网关_第3张图片

可以看到路由动态代理成功,会轮循访问两个生产者

断言 (Predicate)

常用的Route Predicate
1.After Route Predicate
2.Before Route Predicate
3.Between Route Predicate
4.Cookie Route Predicate
5.Header Route Predicate
6.Host Route Predicate
7.Method Route Predicate
8.Path Route Predicate
9.Query Route Predicate

总结Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理

参与官网 https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories

​ 以After Route Predicate为例

​ 意思就是设置一个时间,到某个时间以后才可以通过网关访问,代码如下

spring:
  cloud:
    gateway:
      routes:
      - id: cloud-provider
        uri: lb://cloud-provider
        predicates:
        - After=2020-05-24T02:14:46.014+08:00[Asia/Shanghai]

时间获取方式如下:

import java.time.ZonedDateTime;

/**
 * 
 * @author Zhang Wei
 * @date 2020/5/24 02:13
 * @version v1.0.1
 */
public class Test {
    public static void main(String[] args) {
        ZonedDateTime zt = ZonedDateTime.now();
        System.out.println(zt);
    }
}

其他剩下的几种,可参与官网进行尝试,都有demo

过滤器(Filter)

Filter的生命周期

​ pre(业务逻辑之前) post(业务逻辑之后)

Filter的种类

  • GatewayFilter 单一的
  • GlobalFilter 全局

默认的Filter介绍请参与官网文档,根据介绍直接在yml配置即可

单一Filter https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gatewayfilter-factories

全局Filter https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#global-filters

自定义Filter

​ 实现 GlobalFilter ,Ordered

在gateway添加config包,添加配置类

模拟拦截用户是否带了token

package com.cto.cloud.filter;

import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.result.view.RequestContext;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * 
 * @author Zhang Wei
 * @date 2020/5/19 23:52
 * @version v1.0.1
 */
@Component
public class GlobalTokenFilter implements GlobalFilter, Ordered {
    /**
     * 数字越小 优先级越高
     * @return
     */
    @Override
    public int getOrder() {
        return 1;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //判断第一个参数是不是name,如果是继续,不是则返回自定义错误 Token验证也是一个道理,从header中获取
        String name = exchange.getRequest().getQueryParams().getFirst("name");
        if(StringUtils.isEmpty(name)){
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            byte[] bytes = "{\"status\":\"-1\",\"msg\":\"error\"}".getBytes(StandardCharsets.UTF_8);
            DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
            return exchange.getResponse().writeWith(Flux.just(buffer));
        }
        return chain.filter(exchange);
    }
}

监听没个接口请求的信息

package com.cto.cloud.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 
 * @author Zhang Wei
 * @date 2020/5/19 23:52
 * @version v1.0.1
 */
@Component
public class GlobalRunTimeFilter implements GlobalFilter, Ordered {
    private static final String ELAPSED_TIME_BEGIN = "elapsedTimeBegin";

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

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getAttributes().put(ELAPSED_TIME_BEGIN, System.currentTimeMillis());
        return chain.filter(exchange).then(
            Mono.fromRunnable(() -> {
                Long startTime = exchange.getAttribute(ELAPSED_TIME_BEGIN);
                if (startTime != null) {
                    System.out.println(exchange.getRequest().getURI().getRawPath() + ": " + (System.currentTimeMillis() - startTime) + "ms");
                    System.out.println(exchange.getRequest().getQueryParams());
                }
            })
        );
    }
}

重启gateway8888 访问:http://localhost:8888/provider/getData

Spring CLoud以Eureke为注册中心的服务搭建(七)---Gateway网关_第4张图片

没带参数,gateway直接拦截并没有访问9001或者9002,可自行查看日志

Spring CLoud以Eureke为注册中心的服务搭建(七)---Gateway网关_第5张图片

当带了约定的参数,成功访问

Spring CLoud以Eureke为注册中心的服务搭建(七)---Gateway网关_第6张图片

查看网关后台日志,请求时间Filter也生效

本文是在学习过程中整理,如有错误欢迎各位大佬指正!O(∩_∩)O

Github地址

陆续更新中……

你可能感兴趣的:(Spring,Cloud,学习之路)