• 09_GateWay—网关介绍


    GateWay—网关介绍

    所谓的API网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能天关的公共逻辑可以在这里实现,诸如认证、签权、监控、路由转发等等。添加上API网关之后,系统的架构图变成了如下所示:

    在这里插入图片描述

    优点:

    在这里插入图片描述

    整体微服务结构图,网关Gateway的位置

    在这里插入图片描述

    GateWay介绍

    网关作为流量的入口,常用的功能包括路由转发,权限校验,限流等。

    Spring Cloud Gateway 是Spring Cloud官方推出的第二代网关框架,定位于取代NetflexZuul 1.0。相比Zuul来说,Spring Clout Gateway)提供更优秀的性能,更强大的有功能

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

    Spring Clout Gateway旨在为微服务架构提供一种简单且有效的API路由的管理方式,并基于Filter的方式提供网关的基本功能,例如说安全认证、监控、限流等等。

    功能特征

    • 基于Spring Framework 5,Project Reactor和 Spring Boot 2.0进行构建;
    • 动态路由:能够匹配任何请求属性;
    • 支持路径重写;
    • 集成 Spring Cloud服务发现功能(Nacos、Eruka) ;
    • 可集成流控降级功能(Sentinel、Hystrix) ;
    • 可以对路由指定易于编写的 Predicate (断言)和Filter(过滤器);

    核心概念:

    • 路由

    路由是网关中最基础的部分,路由信息包括一个ID、一个目的URI、一组断言工厂、一组Fiter组成。如果断言为真,则说明请求的URL和配置的路由匹配.

    • 断言(predicates)

    Java8中的断言函数,SprigCloud Gateway中的断言函数类型是Sping5 o框架中的SererWebExchange。断言函数允许开发者去定义匹配Http request中的任何信息,比如请求头和参数等。

    • 过滤器(Fllter)

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

    GateWay—初体验

    1.创建新的子项目gateway 引入依赖

    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-gatewayartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.编写配置文件

    server:
      port: 8088
    spring:
      application:
        name: api-gateway
      cloud:
        #gateway的配置
        gateway:
          #路由配置
          routes:
            - id: order_route  #路由的唯一标识,路由到order
              uri: http://localhost:8020  #需要转发的地址
              #断言规则  用于路由规则的匹配
              predicates:
                - Path=/order-serv/**
                # 请求 http://localhost:8088/order-serv/order/add路由到
                # http://localhost:8020/order-serv/order/add
              filters:
                - StripPrefix=1  #转发之前去掉第一层路径
                # http://localhost:8020/order/add
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    3.主启动类启动

    @SpringBootApplication
    public class GatewayApplication {
        public static void main(String[] args) {
            SpringApplication.run(GatewayApplication.class,args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    访问之前启动 order-nacos 和 stock-nacos模块

    order-nacos模块 controller代码

    @RestController
    @RequestMapping("/order")
    public class OrderController {
        @Autowired
        RestTemplate restTemplate;
    
        @RequestMapping("/add")
        public String add(){
            System.out.println("下单成功!");
            String msg = restTemplate.getForObject("http://stock-service/stock/reduct", String.class);
            return "hello world"+msg;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    stock-nacos模块 controller代码

    @RestController
    @RequestMapping("/stock")
    public class StockController {
    
        @Value("${server.port}")
        String port;
    
        @RequestMapping("/reduct")
        public String reduct(){
            System.out.println("扣减库存");
            return "扣减库存"+port;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    三个模块全部启动

    测试访问 http://localhost:8088/order-serv/order/add

    页面显示 hello world扣减库存8021

    GateWay整合nacos

    现在在配置文件中写死了转发路径的地址,前面我们已经分析过地址写死带来的问题,接下来我们从注册中心获取此地址。

    集成Nacos

    1.再引入依赖

    
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.编写yml配置文件

    server:
      port: 8088
    spring:
      application:
        name: api-gateway
      cloud:
        #gateway的配置
        gateway:
          #路由配置
          routes:
            - id: order_route  #路由的唯一标识,路由到order
              uri: lb://order-service  #需要转发的地址 lb 使用nacos本地负载均衡策略 order-service 服务名  
              predicates:
                - Path=/order-serv/**
              filters:
                - StripPrefix=1  
        #配置Nacos
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    测试访问 http://localhost:8088/order-serv/order/add

    页面显示 hello world扣减库存8021

    简写形式

    • 比较少用
    • 自己去配置断言和过滤器比较好
    server:
      port: 8088
    spring:
      application:
        name: api-gateway
      cloud:
        #gateway的配置
        gateway:
          discovery:
            locator:
              enabled: true #是否启动自动识别nacos服务
        #路由配置
    
        #配置Nacos
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    测试访问 http://localhost:8088/order-service/order/add 用的是服务名

    页面显示 hello world扣减库存8021

    GateWay—内置路由断言工厂

    作用 : 当请求gateway的时候,使用断言对请求进行匹配,如果匹配成功就路由转发,如果匹配失败就返回404

    类型 内置 、自定义

    • 基于Datetime类型的断言工厂

    此类型的断言根据时间做判断,主要有三个:

    AfterRoutePredicateFactory:接收一个日期参数,判断请求日期是否晚于指定日期

    BeforeRoutePredicateFactory:接收一个日期参数,判断请求日期是否早于指定日期

    BetweenRoutePredicateFactory:接收两个日期参数,判断请求日期是否在指定时间段内

    predicates:
    	- Path=/order-serv/**
    	- After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]
    
    • 1
    • 2
    • 3
    • 基于远程地址的断言工厂

    RemoteAddrRoutePredicateFactory:接收一个IP地址段,判断请求主机地址是否在地址段中

    - RemoteAddr=192.168.1.1/24
    
    • 1
    • 基于Cookie的断言工厂

    CookieRoutePredicateFactory: 接收两个参数,cookie名字和一个正则表达式。判断请求cookie是否具有给定名称且值与正则表达式匹配。

    - Cookie=chocolate,ch.
    
    • 1
    • 基于Header的断言工厂

    HeaderRoutePredicateFactory:接收两个参数,标题名称和正则表达式。判断请求Header是否员有给定名称且值与正则表达式匹配.

    - Header=X-Request-Id,\d+
    
    • 1
    • 基于Host的断言工厂

    HostRoutePredicateFactory:接收一个参数,主机名模式。判断请求的Host是否满足匹配规则

    - Host=**.testhost.org
    
    • 1
    • 基于Method请求方法的断言工厂

    MethodRoutePredicateFactory:接收一个参数,判断请求类型是否跟指定的类型匹配。

    - Method=GET
    
    • 1
    • 基于Path请求路径的断言工厂

    PathRoutePredicateFactory:接收一个参数,判断请求的URI部分是否满足路径规则,

    - Path=/foo/{segment}
    
    • 1
    • 基于Query请求参数的断言工厂
    - Query=name,xushu|zhuge  
    #要有name参数 而且要等于xushu或者zhuge
    
    • 1
    • 2

    GateWay—自定义路由断言工厂

    自定义路由断言工厂需要继承AbstractRoutePredicateFactory 类,重写 apply 方法的逻辑。在apply方法中可以通过 exchange.getRequest()拿到ServerhttptRequest对象,从而可以获取到请求的参数、请求方式、请求头等信息.

    1.必须spring组件 bean

    2.类必须加上RoutePredicateFactory作为结尾

    3.必须继承AbstractRoutePredicateFactory

    4.必须声明静态内部类 声明属性来接受 配置文件中的对应的断言的信息

    5.需要结合shortcutFieldOrder进行绑定

    6.通过apply进行逻辑判断 true就是匹配成功 false匹配失败

    写个自定义参数叫CheckAuth 值必须是xushu才可以访问

    package com.tian.predicates;
    
    import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
    import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StringUtils;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.server.ServerWebExchange;
    
    import javax.validation.constraints.NotEmpty;
    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.List;
    import java.util.function.Predicate;
    @Component
    public class CheckAuthRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config> {
    
    
        public CheckAuthRoutePredicateFactory() {
            super(CheckAuthRoutePredicateFactory.Config.class);
        }
    
        public List<String> shortcutFieldOrder() {
            return Arrays.asList("name");
        }
    
        public Predicate<ServerWebExchange> apply(CheckAuthRoutePredicateFactory.Config config) {
            return new GatewayPredicate() {
                public boolean test(ServerWebExchange exchange) {
                    if(config.getName().equals("xushu")){
                        return true;
                    }
                    return false;
                }
    
            };
        }
    //用来接收配置文件中 断言的信息
    @Validated
    public static class Config {
    private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    配置文件

    predicates:
    #- Path=/order-serv/**
    	- Path=/order/**
    	- CheckAuth=xushu
    	#- CheckAuth=xushu2
    
    • 1
    • 2
    • 3
    • 4
    • 5

    访问 http://localhost:8088/order/add xushu就可以正确访问,xushu2页面就会报404

    GateWay—局部(内置、自定义)过滤器

    添加请求头

    #gateway模块配置文件
    spring:
      cloud:
        gateway:
          routes:
          - id: order_route
          uri: http://localhost:8020
          filters:
           - AddRequestHeader=X-Request-color,red  #添加请求头
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    order-nacos模块controller

    @RequestMapping("/header")
    public String header(@RequestHeader("X-Request-color") String color){
        return color;
    
    • 1
    • 2
    • 3

    访问 http://localhost:8088/order/header 页面显示 red

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    自定义过滤器工厂

    • 和断言工厂差不多

    在这里插入图片描述

    配置文件

    filters:
     - CheckAuth=fox,
    • 1
    • 2

    访问输出CheckAuthGatewayFilterFactory===fox: 男

    GateWay—全局过滤器

    局部过滤器和全同过滤器区别:

    局部:局部针对某个路由,需要在路由中进行配置

    全局:针对所有路由请求,你定义就会投入使用

    自定义全局过滤器

    @Component
    public class LogFilter implements GlobalFilter {
        Logger log= LoggerFactory.getLogger(this.getClass());
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            log.info(exchange.getRequest().getPath().value());
            return chain.filter(exchange);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    GateWay—请求日记记录&跨域处理

    要启用Reactor Netty 访问日志,请设置

    -Dreactor.netty.http.server.accessLogEnabled=true.

    在这里插入图片描述

    重启 控制台就会打印输出日志

    它必须是Java系统属性,而不是 Spring Boot属性。

    跨域问题

    配置文件application.yml

    #跨域配置
    spring:
      cloud:
        gateway:
          globalcors:
            cors-configurations:
              '[/**]':  #允许跨域访问的资源
                allowedOrigins: "https://docs.spring.io" #跨域允许来源
                allowedMethods:
                - GET
                - POST
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    配置类配置

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.cors.reactive.CorsWebFilter;
    import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
    import org.springframework.web.util.pattern.PathPatternParser;
    
    @Configuration
    public class CorsConfig {
    
        @Bean
        public CorsWebFilter corsWebFilter(){
            CorsConfiguration config = new CorsConfiguration();
            config.addAllowedMethod("*"); //允许的method
            config.addAllowedOrigin("*"); //允许的来源
            config.addAllowedHeader("*"); //允许的请求头参数
            // 运行访问的资源
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
            source.registerCorsConfiguration("/**",config);
            return new CorsWebFilter(source);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    GateWay—整合Sentinel流控降级

    api-gateway模块

    1.添加依赖

    
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-alibaba-sentinel-gatewayartifactId>
    dependency>
    
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.配置文件

    spring:
      cloud:
      	  #配置sentinel
        sentinel:
          transport:
            dashboard: 127.0.0.1:8888
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.启动sentinel 控制台配置规则

    在这里插入图片描述

    4.访问

    http://localhost:8088/order/add

    现象 前两次正常页面显示 第三次页面显示

    Blocked by Sentinel: ParamFlowException
    
    • 1

    GateWay—整合Sentinel流控降级详细配置

    在这里插入图片描述

    API管理

    在这里插入图片描述

    在这里插入图片描述

    降级

    在这里插入图片描述

    处理方法(在降级规则那配置)

    在这里插入图片描述

    自定义异常

    • 让页面显示自定义异常信息
    package com.tian.config;
    
    import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
    import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.web.reactive.function.BodyInserter;
    import org.springframework.web.reactive.function.BodyInserters;
    import org.springframework.web.reactive.function.server.ServerResponse;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    import javax.annotation.PostConstruct;
    import java.util.HashMap;
    
    @Configuration
    public class GatewayConfig {
        @PostConstruct
        public void init(){
            BlockRequestHandler blockRequestHandler=new BlockRequestHandler() {
                @Override
                public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
    
                    HashMap<String, String> map = new HashMap<>();
                    map.put("code",HttpStatus.TOO_MANY_REQUESTS.toString());
                    map.put("message","限流了");
                    //自定义异常处理
                    return ServerResponse.status(HttpStatus.OK)
                            .contentType(MediaType.APPLICATION_JSON)
                            .body(BodyInserters.fromValue(map));
                }
            };
            GatewayCallbackManager.setBlockHandler(blockRequestHandler);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    或 yml配置

    spring:
      cloud:
      	sentinel:
      	  scg:
            fallback:
              mode: response
              response-body: "{code:'',message:''}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

  • 相关阅读:
    力扣 hot100 -- 技巧
    iMazing 3中文版功能介绍免费下载安装教程
    Design A Youtube
    洛谷 P1716 双调序列
    JAVA计算机毕业设计新能源汽车故障分析2021Mybatis+系统+数据库+调试部署
    java基础巩固12
    准备HarmonyOS开发环境
    基于Java毕业设计学习自律养成小程序后台源码+系统+mysql+lw文档+部署软件
    Ansible 自动化运维详解
    力扣第463题 岛屿的周长 C++ 深度优先搜索 + 思维判断的边界
  • 原文地址:https://blog.csdn.net/xixihaha_coder/article/details/126702341