• SpringCloud中服务熔断组件Hystrix和网关组件Gateway的使用


    9.Hystrix组件使用

    Hystrix组件

    image-20200715123359665

    In a distributed environment, inevitably some of the many service dependencies will fail. Hystrix is a library that helps you control the interactions between these distributed services by adding latency tolerance and fault tolerance logic. Hystrix does this by isolating points of access between the services, stopping cascading failures across them, and providing fallback options, all of which improve your system’s overall resiliency. --[摘自官方]

    # 0.说明
    - https://github.com/Netflix/Hystrix
    - 译: 在分布式环境中,许多服务依赖项不可避免地会失败。Hystrix是一个库,它通过添加延迟容忍和容错逻辑来帮助您控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止它们之间的级联故障以及提供后备选项来实现这一点,所有这些都可以提高系统的整体弹性。
    - 通俗定义: Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统中,许多依赖不可避免的会调用失败,超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障(服务雪崩现象),提高分布式系统的弹性。
    
    
    # 1.作用
    - hystrix 用来保护微服务系统 实现 服务降级  服务熔断
    
    - 服务雪崩  
    - 服务降级
    - 服务熔断
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    1.服务雪崩
    # 1.服务雪崩
    - 在微服务之间进行服务调用是由于某一个服务故障,导致级联服务故障的现象,称为雪崩效应。雪崩效应描述的是提供方不可用,导致消费方不可用并将不可用逐渐放大的过程。
    # 2.图解雪崩效应
    - 如存在如下调用链路:
    
    • 1
    • 2
    • 3
    • 4

    image-20200715151728240

    - 而此时,Service A的流量波动很大,流量经常会突然性增加!那么在这种情况下,就算Service A能扛得住请求,Service B和Service C未必能扛得住这突发的请求。此时,如果Service C因为抗不住请求,变得不可用。那么Service B的请求也会阻塞,慢慢耗尽Service B的线程资源,Service B就会变得不可用。紧接着,Service A也会不可用,这一过程如下图所示
    
    • 1

    image-20200715152623313

    2.服务熔断

    如何解决服务雪崩

    # 服务熔断
    - “熔断器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器(Hystrix)的故障监控,某个异常条件被触发,直接熔断整个服务。向调用方法返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,就保证了服务调用方的线程不会被长时间占用,避免故障在分布式系统中蔓延,乃至雪崩。如果目标服务情况好转则恢复调用。服务熔断是解决服务雪崩的重要手段。
    
    熔断类似于保险丝,熔断是对别的服务的保护,防止故障扩大范围。
    熔断就是做一个快速的返回,调用的时候不用再看了,快速返回当前服务不可用
    # 服务熔断图示
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    image-20200717085946385

    3.服务降级
    # 服务降级说明
    - 服务压力剧增的时候根据当前的业务情况及流量对一些服务和页面有策略的降级,以此缓解服务器的压力,以保证核心任务的进行。同时保证部分甚至大部分任务客户能得到正确的响应。也就是当前的请求处理不了了或者出错了,给一个默认的返回。
    
    - 服务降级: 关闭微服务系统中某些边缘服务 保证系统核心服务正常运行
    - 12 淘宝  京东
    - 删除订单 --- 关闭订单    确认收货 ---->     服务繁忙,!!!
    
    # 服务降级图示
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    image-20200717112327729

    4.降级和熔断总结
    # 1.共同点
    - 目的很一致,都是从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃,采用的技术手段;
    - 最终表现类似,对于两者来说,最终让用户体验到的是某些功能暂时不可达或不可用;
    - 粒度一般都是服务级别,当然,业界也有不少更细粒度的做法,比如做到数据持久层(允许查询,不允许增删改);
    - 自治性要求很高,熔断模式一般都是服务基于策略的自动触发,降级虽说可人工干预,但在微服务架构下,完全靠人显然不可能,开关预置、配置中心都是必要手段;sentinel
    
    # 2.异同点
    - 触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;
    - 管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务边缘服务开始)
    
    # 3.总结
    - 熔断必会触发降级,所以熔断也是降级一种,区别在于熔断是对调用链路的保护,而降级是对系统过载的一种保护处理
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    5.服务熔断的实现(服务方的熔断)

    例如商品服务调用库存服务库存服务此时处理不过来,但是还没有宕机,我们在库存服务处实现服务熔断

    # 0.服务熔断的实现思路
    - 引入hystrix依赖,并开启熔断器(断路器)
    - 模拟降级方法
    - 进行调用测试
    
    一旦断路器打开,所有到这个服务的请求均不可用,只有在断路器关闭之后才可用
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    # 1.项目中引入hystrix依赖 (所有服务中必须引入Hystrix组件)
    一旦服务引入Hystrix依赖,这个服务就具有服务熔断功能
    
    • 1
    • 2
    
    <dependency>
      <groupId>org.springframework.cloudgroupId>
      <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    # 2.开启断路器
    在入口类上加上@EnableCircuitBreaker注解
    
    • 1
    • 2
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableCircuitBreaker       // 开启Hystrix服务熔断器
    public class HystrixApplication {
        public static void main(String[] args) {
            SpringApplication.run(HystrixApplication.class, args);
        }
    }
    /*
    注意:现在 @EnableCircuitBreaker 注解不推荐使用了,推荐使用@EnableHystrix 注解
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    # 3.使用 @HystrixCommand注解 实现断路
    
    • 1
    @RestController
    public class DemoController {
    
        @GetMapping("/demo")
        @HystrixCommand(fallbackMethod = "demoFallBack")    // 熔断之后如何处理:调用快速失败的处理方法
        public String demo(Integer id){
            if(id <= 0){
                throw new RuntimeException();
            }
            System.out.println("demo ok!!!");
            return "demo ok";
        }
    
        // 熔断之后走这个方法,不再走上面 demo 方法了
        public String demoFallBack(Integer id){     // 处理快速失败的这个方法返回值、参数列表必须和上面失败方法一致
            return "网络繁忙,请稍后再试";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    image-20200717090743474

    # 4.访问测试
    - 正常参数访问
    - 错误参数访问
    
    • 1
    • 2
    • 3

    image-20200717090841831

    image-20200717091028876

    # 5.总结
    - 从上面演示过程中会发现如果触发一定条件断路器会自动打开,过了一点时间正常之后又会关闭。那么断路器打开条件是什么呢?
    
    • 1
    • 2
    # 6.断路器打开条件
    - 官网: https://cloud.spring.io/spring-cloud-netflix/2.2.x/reference/html/#circuit-breaker-spring-cloud-circuit-breaker-with-hystrix
    
    • 1
    • 2

    A service failure in the lower level of services can cause cascading failure all the way up to the user. When calls to a particular service exceed circuitBreaker.requestVolumeThreshold (default: 20 requests) and the failure percentage is greater than circuitBreaker.errorThresholdPercentage (default: >50%) in a rolling window defined by metrics.rollingStats.timeInMilliseconds (default: 10 seconds), the circuit opens and the call is not made. In cases of error and an open circuit, a fallback can be provided by the developer. --摘自官方

    # 原文翻译之后,总结打开关闭的条件:
    - 1、  当满足一定的阀值的时候(默认10秒内超过20个请求失败)
    - 2、  当失败率达到一定的时候(默认10秒内超过50%的请求失败)
    - 3、  到达以上阀值,断路器将会开启
    - 4、  当开启的时候,所有请求都不会进行转发
    - 5、  一段时间之后(默认是5秒),这个时候断路器是半开状态,会让其中一个请求进行转发。如果成功,断路器会关闭,若失败,继续开启。重复4和5。
    
    # 面试重点问题: 断路器流程
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    image-20200717092819616

    # 7.默认的服务FallBack处理方法
    - 如果为每一个服务方法开发一个降级,对于我们来说,可能会出现大量的代码的冗余,不利于维护,这个时候就需要加入默认服务降级处理方法
    
    默认服务FallBack处理方法是站在controller角度,不同的controller也都需要写。一个controller写一个。
    日后一个controller中的不同接口不需要自定义处理方法了,只需要写一个方法,然后默认指向这个方法就可以了。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    @RestController
    public class DemoController {
    
        @GetMapping("/demo")
        @HystrixCommand(defaultFallback = "defaultFallBack") //默认备选处理,使用@HystrixCommand注解的defaultFallback属性
        public String demo(Integer id){
            if(id <= 0){
                throw new RuntimeException();
            }
            System.out.println("demo ok!!!");
            return "demo ok";
        }
        // 默认的处理方法              默认的处理方法不能写参数,因为每一个接口参数都不一样
        public String defaultFallBack(){
            return "网络连接失败,请重试!!!";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    6.服务降级的实现(调用方的熔断)

    商品服务使用Openfeign调用库存服务,但是此时库存服务已经宕机,库存服务无法再给商品服务熔断时的备选方案了,我们应该在商品服务处提供一个快速失败的策略。

    引入Hystrix依赖

    注:Openfeign底层已经引入了Hystrix,所以如果已经引入Openfeign无需再引入Hystrix依赖

    
    <dependency>
      <groupId>org.springframework.cloudgroupId>
      <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    # 服务降级: 站在系统整体负荷角度 实现: 关闭系统中某些边缘服务 保证系统核心服务运行
    	Emps 核心服务   Depts 边缘服务
    
    # 1.客户端openfeign + hystrix实现服务降级实现
    - 引入hystrix依赖
    - 配置文件开启feign支持hystrix
    - 在feign客户端调用加入fallback指定降级处理
    - 开发降级处理方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    # 2.开启openfeign支持服务降级
    
    • 1
    #开启openfeign支持降级
    feign.hystrix.enabled=true 
    
    • 1
    • 2
    # 3.在openfeign客户端中加如Hystrix
    
    • 1
    @FeignClient(value = "HYSTRIX", fallback = ProductClientFallBack.class)  // fallback:这个属性用来指定当调用的服务不可用时,默认的备选处理
    public interface ProductClient {
    
        @GetMapping("/demo")
        String demo(@RequestParam("id") Integer id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    # 4.开发fallback处理类(实现OpenfeignClient的接口)
    
    • 1
    // 自定义备选方案
    @Component    // 这个类肯定要在工厂中注册
    public class ProductClientFallBack implements ProductClient{
        @Override
        public String demo(Integer id) {
            return "当前服务不可用,请稍后再试! id: " + id;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    7.Hystrix Dashboard(仪表盘)【不建议用,配置极其麻烦】
    # Hystrix DashBoard 仪表盘 
    
    # 0.说明
    - Hystrix Dashboard的一个主要优点是它收集了关于每个HystrixCommand的一组度量。Hystrix仪表板以高效的方式显示每个断路器的运行状况。
    
    • 1
    • 2
    • 3
    • 4

    image-20200716161556743

    日后在开发的时候单独创建一个springboot应用,但是这个应用里面没有任何的业务代码(但是要有入口类和配置文件端口)。这个应用不需要注册到服务中心,这个应用只是起到起到一个监控的作用。

    这个应用首先要引入springboot依赖

    <dependencies>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
    dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    # 1.项目中引入依赖
    
    • 1
    
    <dependency>
      <groupId>org.springframework.cloudgroupId>
      <artifactId>spring-cloud-starter-netflix-hystrix-dashboardartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    # 2.入口类上加上@EnableHystrixDashboard注解开启hystrix dashboard
    
    • 1
    @SpringBootApplication
    @EnableHystrixDashboard     //开启当前应用为仪表盘应用
    public class HystrixDashboardApplication {
        public static void main(String[] args) {
            SpringApplication.run(HystrixDashboardApplication.class, args);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    # 3.启动hystrix dashboard应用
    - http://localhost:9099/hystrix
    
    ( 9099 是 应用端口,hystrix 不是服务名,是固定的)
    
    • 1
    • 2
    • 3
    • 4

    image-20200717155059512

    # 4.监控的项目中入口类中加入监控路径配置[新版本坑],并启动监控项目
    
    • 1
    @Bean
    public ServletRegistrationBean getServlet() {
      HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
      ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
      registrationBean.setLoadOnStartup(1);
      registrationBean.addUrlMappings("/hystrix.stream");
      registrationBean.setName("HystrixMetricsStreamServlet");
      return registrationBean;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    image-20200717155120335

    # 5.通过监控界面监控
    
    • 1

    image-20200717155258994

    # 6.点击监控,一直loading,打开控制台发现报错[特别坑]
    
    • 1

    image-20200717155555786

    # 解决方案
    - 新版本中springcloud将jquery版本升级为3.4.1,定位到monitor.ftlh文件中,js的写法如下:
    	$(window).load(function() 
    	
    - jquery 3.4.1已经废弃上面写法
    
    - 修改方案 修改monitor.ftlh为如下调用方式:
    	$(window).on("load",function()
    	
    - 编译jar源文件,重新打包引入后,界面正常响应。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    image-20200717160636218

    8.Hystrix停止维护

    image-20200717161223806

    image-20200717161400285

    # 官方地址:https://github.com/Netflix/Hystrix
    - 翻译:Hystrix(版本1.5.18)足够稳定,可以满足Netflix对我们现有应用的需求。同时,我们的重点已经转移到对应用程序的实时性能作出反应的更具适应性的实现,而不是预先配置的设置(例如,通过自适应并发限制)。对于像Hystrix这样的东西有意义的情况,我们打算继续在现有的应用程序中使用Hystrix,并在新的内部项目中利用诸如resilience4j这样的开放和活跃的项目。我们开始建议其他人也这样做。 ----> sentinel 流量卫兵
    - Dashboard也被废弃
    
    • 1
    • 2
    • 3

    10.Gateway组件使用

    什么是服务网关

    # 1.说明
    - 网关统一了服务入口,可方便实现对平台众多服务接口进行管控,对访问服务的身份认证、防报文重放与防数据篡改、功能调用的业务鉴权、响应数据的脱敏、流量与并发控制,甚至基于API调用的计量或者计费等等。
    - 网关 =  路由转发 + 过滤器
    	`路由转发:接收一切外界请求,转发到后端的微服务上去;
    	`在服务网关中可以完成一系列的横切功能,例如权限校验、限流以及监控等,这些都可以通过过滤器完成
    	
    # 2.为什么需要网关
     - 1.网关可以实现服务的统一管理
     - 2.网关可以实现路由转发(根据前端不同的请求路径转发到后端的对应服务)以及请求过程中的负载均衡
     - 3.网关可以解决微服务中通用代码的冗余问题(如访问服务的身份验证,权限控制,后端响应数据给前端数据的脱敏(过滤敏感词),流量监控,限流等)
    
    # 3.网关组件在微服务中架构
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    image-20200720171205828

    服务网关组件

    zuul 1.x 2.x(netflix 组件)

    Zuul is the front door for all requests from devices and web sites to the backend of the Netflix streaming application. As an edge service application, Zuul is built to enable dynamic routing, monitoring, resiliency and security.

    # 0.原文翻译
    - https://github.com/Netflix/zuul/wiki
    - zul是从设备和网站到Netflix流媒体应用程序后端的所有请求的前门。作为一个边缘服务应用程序,zul被构建为支持动态路由、监视、弹性和安全性。
    
    # 1.zuul版本说明
    - 目前zuul组件已经从1.0更新到2.0,但是作为springcloud官方不再推荐使用zuul2.0,但是依然支持zuul2.
    
    # 2.springcloud 官方集成zuul文档
    - https://cloud.spring.io/spring-cloud-netflix/2.2.x/reference/html/#netflix-zuul-starter
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    gateway (spring)

    This project provides a library for building an API Gateway on top of Spring MVC. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.

    # 0.原文翻译
    - https://spring.io/projects/spring-cloud-gateway
    - 这个项目提供了一个在springmvc之上构建API网关的库。springcloudgateway旨在提供一种简单而有效的方法来路由到api,并为api提供横切关注点,比如:安全性、监控、度量和弹性。
    
    # 1.特性
    - 基于springboot2.x 和 spring webFlux 和 Reactor 构建 响应式异步非阻塞IO模型
    - 动态路由
    - 请求过滤
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1.开发网关动态路由
    # 0.翻译
    - 网关配置有两种方式一种是快捷方式(Java代码编写网关),一种是完全展开方式(配置文件方式)[推荐]
    
    # 1.创建项目引入网关依赖
    我们要创建一个独立的springboot应用作为网关,网关服务也需要注册到服务中心(引入consul依赖)
    虽然它是一个springboot应用,但是这里我们不引入springboot依赖,因为spring-boot-starter-web和gateway存在冲突,将spring-boot-starter-web依赖去掉
    
    
    
      org.springframework.cloud
      spring-cloud-starter-consul-discovery
    
    
    
    
      org.springframework.boot
      spring-boot-starter-actuator
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    
    <dependency>
      <groupId>org.springframework.cloudgroupId>
      <artifactId>spring-cloud-starter-gatewayartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 快捷方式配置路由[推荐]
    # 2.编写网关配置
    网管配置文件编写极其复杂,不建议使用properties形式,建议使用yml形式
    
    • 1
    • 2
    server:
      port: 7979        # 端口
    spring:
      application:
        name: GATEWAY   # 应用名字
      cloud:
        consul:         # 注册到consul注册中心
          host: localhost
          port: 8500
        gateway:        # 路由配置
          routes:
            - id: category_route            # 路由对象唯一标识
              uri: http://localhost:8787/   # 指定路由服务的地址,category服务的端口就是8787 (例如访问http://localhost:7979/category转到http://localhost:8787/category)
              predicates:                   # 断言:用来配置路由规则
                - Path=/category/**         # 通配符*  匹配/category下所有路径
    
            - id: product_route             # 路由对象唯一标识
              uri: http://localhost:8799/   # 指定路由服务的地址,product服务的端口就是8799 (例如访问http://localhost:7979/product转到http://localhost:8799/product)
              predicates:                   # 断言:用来配置路由规则
                - Path=/product/**
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    # 3.启动gateway网关项目
    - 直接启动报错:
    
    • 1
    • 2

    image-20200720212535357

    - 在启动日志中发现,gateway为了效率使用webflux进行异步非阻塞模型的实现,因此和原来的web包冲突,去掉原来的web即可
    去掉下面的spring-boot-starter-web依赖
    
    
      org.springframework.boot
      spring-boot-starter-web
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    image-20200720212653494

    - 再次启动成功启动
    
    • 1

    image-20200720213657788

    # 4.测试网关路由转发
    - 测试通过网关访问用户服务: http://localhost:7979/category
    - 测试通过网关访问商品服务: http://localhost:7979/product
    
    • 1
    • 2
    • 3
    • java方式配置路由[不推荐]
    @Configuration
    public class GatewayConfig {
        @Bean
        public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
            return builder.routes()
                    // 类别路由
                    .route("category_route", r -> r.path("/category/**")
                            .uri("http://localhost:8787"))
                    // 商品路由
                    .route("product_route", r -> r.path("/product/**")
                            .uri("http://localhost:8799"))
                    .build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    2. 网关路由解析规则

    33.路由解析规则

    3.配置路由服务负载均衡
    # 1.说明
    - 现有路由配置方式,都是基于服务地址写死的配置进行路由转发,能不能根据服务名称进行路由转发同时实现负载均衡的呢?
    
    # 2.动态路由以及负载均衡转发配置
    
    • 1
    • 2
    • 3
    • 4
    server:
      port: 7979        # 端口
    spring:
      application:
        name: GATEWAY   # 应用名字
      cloud:
        consul:         # 注册到consul注册中心
          host: localhost
          port: 8500
        gateway:        # 路由配置
          routes:
            - id: category_route            # 路由对象唯一标识
              # uri: http://localhost:8787/   # 指定路由服务的地址,category服务的端口就是8787 (例如访问http://localhost:7979/category转到http://localhost:8787/category)
              uri: lb://CATEGORY            # lb代表转发后台服务使用负载均衡,CATEGORY代表服务注册中心上的服务名
              predicates:                   # 断言:用来配置路由规则
                - Path=/category/**         # 通配符*  匹配/category下所有路径
    
            - id: product_route             # 路由对象唯一标识
              # uri: http://localhost:8799/   # 指定路由服务的地址,product服务的端口就是8799 (例如访问http://localhost:7979/product转到http://localhost:8799/product)
              uri: lb://PRODUCT             # lb(loadbalance)代表负载均衡转发路由, PRODUCT是服务名
              predicates:                   # 断言:用来配置路由规则
                - Path=/product/**
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    image-20200721110040104

    4.常用路由predicate(断言,验证)

    断言:当请求到达网关时,网关前置处理,满足断言放行请求不满足断言立即返回

    过滤:当请求满足断言的所有条件之后,会向后端服务转发,在向后端服务转发之前会经过一系列过滤

    在这里插入图片描述

    # 1.Gateway支持多种方式的predicate
    
    • 1

    image-20200721112751340

    - Path=/user/**																					# 路径断言,路径必须包含指定路径
    
    - After=2022-09-07T13:56:40.096+08:00[Asia/Shanghai]  	# 代表该路由规则在指定时间之后才能生效,
    																												# 比如一些功能,到指定时间才开放
    
    - Before=2022-09-07T13:56:40.096+08:00[Asia/Shanghai]   # 代表该路由规则在指定时间之前才生效
    																												  
    - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]                                   # 代表路由规则在指定时间段内生效
    
    																																			
    - Cookie=username,chenyn																#	表示请求必须携带指定cookie才能访问
     # cookie键必须是username,值必须是chenyn才能访问,如果想写多个cookie,在下一行写Cookie=xxx,xxx	
     # curl http://localhost:7979/product/product --cookie "username=chenyn"
    
    - Cookie=username,[A-Za-z0-9]+													#携带的cookie键必须是username,
    																												#值符合后面的正则才可以访问
    	# curl http://localhost:7979/product/product --cookie "username=xxx"
    
    - Header=X-Request-Id,\d+															 #	 必须携带指定的Header信息才可以访问
    																						# 基于请求头中的指定属性的正则匹配路由(这里全是整数)
    
      # curl http://localhost:7979/product/product -H "X-Request-Id:11"
    
    - Method=GET																		# 必须是指定的请求方式才可以访问
    	# Method=POST	  指定请求方式必须是POST才可以访问
    
    - 官方更多: https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.3.RELEASE/reference/html/#the-cookie-route-predicate-factory
    
    • 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
    # 2.使用predicate
    
    • 1
    server:
      port: 7979        # 端口
    spring:
      application:
        name: GATEWAY   # 应用名字
      cloud:
        consul:         # 注册到consul注册中心
          host: localhost
          port: 8500
        gateway:        # 路由配置
          routes:
            - id: category_route            # 路由对象唯一标识
              # uri: http://localhost:8787/   # 指定路由服务的地址,category服务的端口就是8787 (例如访问http://localhost:7979/category转到http://localhost:8787/category)
              uri: lb://CATEGORY            # lb代表转发后台服务使用负载均衡,CATEGORY代表服务注册中心上的服务名
              predicates:                   # 断言:用来配置路由规则
                - Path=/category/**         # 通配符*  匹配/category下所有路径
    
            - id: product_route             # 路由对象唯一标识
              # uri: http://localhost:8799/   # 指定路由服务的地址,product服务的端口就是8799 (例如访问http://localhost:7979/product转到http://localhost:8799/product)
              uri: lb://PRODUCT             # lb(loadbalance)代表负载均衡转发路由, PRODUCT是服务名
              predicates:                   # 断言:用来配置路由规则
                - Path=/product/**
                - After=2022-09-07T14:03:30.898+08:00[Asia/Shanghai]     # 表示路由规则在指定时间之后才生效
                # - Before=2022-09-07T14:08:00.898+08:00[Asia/Shanghai]      # 表示路由规则在指定时间之前才生效
                # - Cookie=username,chenyn   	# 表示请求必须携带指定cookie才能访问,cookie的键必须是username,值必须是chenyn才能访问
                # - Cookie=username,[A-Za-z0-9]+		#携带的cookie键必须是username, 值符合后面的正则才可以访问
                # - Header=X-Request-Id,\d+      # 必须携带指定的Header信息才可以访问, 基于请求头中的指定属性的正则匹配路由(这里全是整数)
                - Method=GET                    # 必须是指定的请求方式才放行
    
    • 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

    image-20220907145601237

    5.常用的Filter以及自定义filter

    过滤:当请求满足断言的所有条件之后,会向后端服务转发,在向后端服务转发之前会经过一系列过滤

    Route filters allow the modification of the incoming HTTP request or outgoing HTTP response in some manner. Route filters are scoped to a particular route. Spring Cloud Gateway includes many built-in GatewayFilter Factories.

    # 1.原文翻译
    - 官网: 
    	https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.3.RELEASE/reference/html/#gatewayfilter-factories
    	
    - 路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。路由筛选器的作用域是特定路由。springcloudgateway包括许多内置的GatewayFilter工厂。
    
    # 2.作用
    - 当我们有很多个服务时,比如下图中的user-service、order-service、product-service等服务,客户端请求各个服务的Api时,每个服务都需要做相同的事情,比如鉴权、限流、日志输出等。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    image-20200721161002001

    image-20200721161421845

    # 2.使用内置过滤器
    
    • 1

    image-20200721152425733

    - AddRequestHeader=User_Name, chenyn							# 给路由对象的转发请求添加指定的请求头
    
    - AddRequestParameter=color, blue									# 给路由对象的转发请求添加指定的请求参数
    																								  # 参数名叫color 值为blue,接收类型为String
    
    - AddResponseHeader=X-Response-Red, Blue					# 响应时做的处理,往响应头里增加信息
    
    - PrefixPath=/product															# 用来给路由对象的转发请求的url加入指定前缀
      # 例如地址栏输入 http://localhost:7979/list 变成 http://localhost:7979/product/list
     
    - StripPrefix=1																# 用来给路由对象的转发请求的url去掉指定的n级前缀
    	# 例如地址栏输入 http://localhost:7979/product/list 会变成 http://localhost:7979/list
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    image-20220907163523771

    # 3.使用自定义filter
    
    • 1
    /**
     * 自定义网关filter
     */
    @Configuration
    public class CustomGlobalFilter implements GlobalFilter, Ordered {
    
        // exchange: 交换  封装了 request 和 response
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            // 相当于httprequest对象
            ServerHttpRequest request = exchange.getRequest();
            // 相当于httpresponse对象
            ServerHttpResponse response = exchange.getResponse();
            System.out.println("经过filter处理..");
            Mono<Void> filter = chain.filter(exchange);       // 放行请求,在微服务中执行完之后响应时向下执行
            System.out.println("响应回来filter处理...");
            return filter;
        }
    
        // order 排序  为了让很多的filter按顺序执行 给每个filter指定一个数字 默认按照从小到大顺序执行
        // 返回 -1 表示在所有filter之前执行,最先执行
        @Override
        public int getOrder() {
            return 1;
        }
    }
    
    • 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
    6.通过网关提供的web路径查看网关路由规则列表
    # 1.说明
    - gateway提供路由访问规则列表的web界面,但是默认是关闭的,如果想要查看服务路由规则可以在配置文件中开启
    
    • 1
    • 2
    management:
      endpoints:
        web:
          exposure:
            include: "*"   # 开启所有web端点暴露
    
    • 1
    • 2
    • 3
    • 4
    • 5
    - 访问路由管理列表地址
    - http://localhost:7979/actuator/gateway/routes
    
    /actuator/gateway/routes 是固定的
    
    7979 是网关服务的端口
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    image-20220907172124261


    总结

    35.网关断言predicate的使用

    36.网关过滤使用和自定义全局filter以及路由规则详细查看

  • 相关阅读:
    【小月电子】FPGA开发板(XLOGIC_V1)系统学习教程-LESSON1点亮LED灯
    进程,内核线程,用户线程,协程,纤程......操作系统世界观
    什么是云计算中的资源调度,解释资源调度的挑战和算法
    类和对象-java
    【Web】CSS学习笔记之浮动*
    聊聊 Netty 那些事儿之 Reactor 在 Netty 中的实现
    ros2 --nav2
    Linux 操作系统云服务器安装部署 Tomcat 服务器详细教程
    十个一手app拉新地推拉新推广接单平台,放单/接任务渠道
    ModStartCMS v7.2.0 匿名点赞功能,注册站内信
  • 原文地址:https://blog.csdn.net/qq_50313418/article/details/126750520