• 20200523 尚硅谷2020最新版SpringCloud【笔记】2


    尚硅谷2020最新版SpringCloud【笔记】2

    10.Hystrix断路器

    概述

    微服务链路调用

    扇出

    服务雪崩

    Hystrix 是一个用于处理分布式系统的延迟容错的开源库

    能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性

    向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常

    Hystrix官宣,停更进维

    Github 地址

    主要功能

    • 服务降级
    • 服务熔断
    • 接近实时的监控

    Hystrix重要概念

    服务降级(fallback)

    服务器忙,请稍候再试,不让客户端等待并立刻返回一个友好提示,fallback

    一般用于客户端,即服务消费者

    哪些情况会触发降级

    • 程序运行异常
    • 超时
    • 服务熔断触发服务降级
    • 线程池/信号量打满也会导致服务降级

    服务熔断(break)

    类比保险丝,达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示

    服务的降级->进而熔断->恢复调用链路

    当失败的调用到一定阈值,默认是5秒内20次调用失败,就会启动熔断机制

    img

    服务限流(flowlimit)

    秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行

    降级容错解决的要求

    • 超时导致服务器变慢(转圈)
      超时不再等待
    • 出错(宕机或程序运行出错)
      出错要有兜底

    Hystrix案例

    服务生产者

    1. 建 Module,cloud-provider-hystrix-payment8001

    2. 改 POM

      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
      </dependency>
      
    3. 改 YML

    4. 主启动类,添加注解 @EnableCircuitBreaker

    5. 服务降级,改业务服务类

      // 超时时间设置为 3s
      @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")})
      public String paymentInfo_TimeOut(Integer id) {
          // 程序异常
          int age = 10 / 0;
      
          // 超时
          // try {
          //     TimeUnit.MILLISECONDS.sleep(5000);
          // } catch (InterruptedException e) {
          //     e.printStackTrace();
          // }
      
          return "线程池:  " + Thread.currentThread().getName() + " id:  " + id + "	" + "O(∩_∩)O哈哈~" + "  耗时(秒): ";
      }
      
      public String paymentInfo_TimeOutHandler(Integer id) {
          return "线程池:  " + Thread.currentThread().getName() + "  8001系统繁忙或者运行报错,请稍后再试,id:  " + id + "	" + "o(╥﹏╥)o";
      }
      
    6. 服务熔断

      @HystrixCommand 注解中可配的属性位于 com.netflix.hystrix.HystrixCommandProperties

      @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback", commandProperties = {@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),// 是否开启断路器
              @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),// 请求次数
              @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), // 时间窗口期
              @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"),// 失败率达到多少后跳闸
      })
      public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
          if (id < 0) {
              throw new RuntimeException("******id 不能负数");
          }
          String serialNumber = IdUtil.simpleUUID();
      
          return Thread.currentThread().getName() + "	" + "调用成功,流水号: " + serialNumber;
      }
      
      public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) {
          return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~   id: " + id;
      }
      

      localhost:8001//payment/circuit/1 返回正常,localhost:8001//payment/circuit/-1 会触发降级,多次触发降级后,访问正常 URL,发现返回的是降级后的响应,一段时间后,恢复正常。

    服务消费者

    1. 建 Module,cloud-consumer-feign-hystrix-order80

    2. 改 POM,同上

    3. 改 YML

      feign:
        hystrix:
          enabled: true
      
    4. 主启动类,添加注解 @EnableHystrix

    5. 服务降级,Controller 调用 Feign 接口

      // 超时时间 2s
      @GetMapping("/consumer/payment/hystrix/timeout/{id}")
      @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod", commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")})
      public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
          // 程序异常
          // int age = 10 / 0;
      
          String result = paymentHystrixService.paymentInfo_TimeOut(id);
          return result;
      }
      
      public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id) {
          return "我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o  " + id;
      }
      
    6. 服务降级,Controller 全局服务降级

      @RestController
      @Slf4j
      @DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
      public class OrderHystirxController {
      	@Resource
          private PaymentHystrixService paymentHystrixService;
          
          @GetMapping("/consumer/payment/hystrix/timeout/{id}")
          @HystrixCommand
          public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
              // 程序异常
              // int age = 10 / 0;
      
              String result = paymentHystrixService.paymentInfo_TimeOut(id);
              return result;
          }
          
          public String payment_Global_FallbackMethod() {
              return "Global异常处理信息,请稍后再试,/(ㄒoㄒ)/~~";
          }
      }
      
    7. 服务降级,通配服务降级,针对 Feign 接口的调用

      1. 实现 Feign 接口
      @Component
      public class PaymentFallbackService implements PaymentHystrixService {
          @Override
          public String paymentInfo_OK(Integer id) {
              return "-----PaymentFallbackService fall back-paymentInfo_OK ,o(╥﹏╥)o";
          }
      
          @Override
          public String paymentInfo_TimeOut(Integer id) {
              return "-----PaymentFallbackService fall back-paymentInfo_TimeOut ,o(╥﹏╥)o";
          }
      }
      
      1. Feign 接口添加注解属性 org.springframework.cloud.openfeign.FeignClient#fallback
      @Component
      @FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT" ,fallback = PaymentFallbackService.class)
      public interface PaymentHystrixService {
          @GetMapping("/payment/hystrix/ok/{id}")
          public String paymentInfo_OK(@PathVariable("id") Integer id);
      
          @GetMapping("/payment/hystrix/timeout/{id}")
          public String paymentInfo_TimeOut(@PathVariable("id") Integer id);
      }
      

    服务熔断原理

    熔断类型

    • 熔断打开
      请求不再进行调用当前服务,内部设置时钟一般为MTTR(平均故障处理时间),当打开时长达到所设时钟则进入熔断状态
    • 熔断关闭
      熔断关闭不会对服务进行熔断
    • 熔断半开
      部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断

    断路器开启或者关闭的条件

    1. 当满足一定阀值的时候(默认10秒内超过20个请求次数)
    2. 当失败率达到一定的时候(默认10秒内超过50%请求失败)
    3. 到达以上阀值,断路器将会开启
    4. 当开启的时候,所有请求都不会进行转发
    5. 一段时间之后(默认是5秒),这个时候断路器是半开状态,会让其中一个请求进行转发。如果成功,断路器会关闭,若失败,继续开启。重复4和5

    Hystrix工作流程

    GitHub 地址

    img

    服务监控 Hystrix Dashboard

    监控的微服务需要依赖 pring-boot-starter-actuator

    创建步骤

    1. Module,cloud-consumer-hystrix-dashboard9001

    2. POM

      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
      </dependency>
      
    3. YML

    4. 主启动类,添加注解 @EnableHystrixDashboard

    5. 启动程序,访问 http://localhost:9001/hystrix

    断路器演示

    1. 改造被监控的微服务

      /**
       *此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑
       *ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
       *只要在自己的项目里配置上下面的servlet就可以了
       */
      @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;
      }
      
    2. 访问 http://localhost:9001/hystrix

    3. 填写 http://localhost:8001/hystrix.stream

    11.zuul路由网关

    跳过,可以看之前的视频:

    尚硅谷经典SpringCloud框架开发教程全套完整版从入门到精通(大牛讲授spring cloud)

    12.Gateway新一代网关

    概述

    Spring Cloud Gateway 使用的 Webflux 中的 reactor-netty 响应式编程组件,底层使用了 Netty 通讯框架

    官网

    Zuul

    Gateway

    主要功能

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

    对比 Zuul 和 Gateway

    Zuul

    Zuul 1进入维护阶段,Zuul 2 一直跳票

    在 Spring Cloud F 版,推荐使用 Zuul

    基于 Servlet 2.5 使用 阻塞 IO 架构

    Gateway

    Servlet 3.1 之后有了异步非阻塞的支持

    Gateway 基于异步非阻塞模型

    Spring Cloud Gateway 具有如下特性:

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

    三大核心概念

    Spring Cloud Gateway Diagram

    • Route(路由)

      路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由

    • Predicate(断言)

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

    • Filter(过滤)

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

    核心逻辑

    路由转发+执行过滤器链

    入门案例

    1. Module,cloud-gateway-gateway9527

    2. POM

      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-gateway</artifactId>
      </dependency>
      
    3. YML

      spring:
        application:
          name: cloud-gateway
        cloud:
          gateway:
            routes:
              - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
                uri: http://localhost:8001          #匹配后提供服务的路由地址
                predicates:
                  - Path=/payment/get/**         # 断言,路径相匹配的进行路由
      
              - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
                uri: http://localhost:8001          #匹配后提供服务的路由地址
                predicates:
                  - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
      
    4. 主启动类

    5. 测试

      直接访问原服务路径 localhost:8001/payment/get/1localhost:8001/payment/lb,可以成功

      通过网关访问服务 localhost:9527/payment/get/1localhost:9527/payment/lb,可以成功

    编码方式配置

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route("path_route_atguigu", r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
        return routes.build();
    }
    

    配置动态路由

    默认情况下Gateway会根据注册中心的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能

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

    Predicate的使用

    官网文档

    配置的都是 org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory 接口的实现类

    Filter的使用

    生命周期

    • pre

      在业务逻辑之前

    • post

      在业务逻辑之后

    种类

    自定义全局GlobalFilter

    /**
     * 要求请求中带参数 uname,否则返回 406, "Not Acceptable"
     */
    @Component
    @Slf4j
    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;
        }
    }
    

    13.SpringCloud Config分布式配置中心

    概述

    官网文档

    不同微服务应用的所有环境提供一个中心化的外部配置

    SpringCloud Config 分为服务端和客户端

    服务端也称为分布式配置中心,是一个独立的微服务应用

    主要功能

    • 集中管理配置文件

    • 不同环境不同配置,动态化的配置更新,分环境部署比如dev/test/prod/beta/release

    • 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息

    • 当配置发生变动时,服务不需要重启即可感知到配置的变化并应用新的配置

    • 将配置信息以REST接口的形式暴露

      post、curl访问刷新均可....

    Config服务端配置与测试

    1. Module,cloud-config-center-3344

    2. POM

      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-config-server</artifactId>
      </dependency>
      
    3. YML

      server:
        port: 3344
      
      spring:
        application:
          name:  cloud-config-center #注册进Eureka服务器的微服务名
        cloud:
          config:
            server:
              git:
      #          uri: git@github.com:liuxing5yu/config-repo.git #GitHub上面的git仓库名字
                uri: https://github.com/liuxing5yu/config-repo #GitHub上面的git仓库名字
            ####读取分支
            label: master
      
      #服务注册到eureka地址
      eureka:
        client:
          service-url:
            defaultZone: http://localhost:7001/eureka
      
    4. 主启动类,添加注解 @EnableConfigServer

    5. 测试,访问 URL http://localhost:3344/master/configclient-dev.yml

    配置读取规则

    • /{application}/{profile}[/{label}]
    • /{application}-{profile}.yml
    • /{label}/{application}-{profile}.yml
    • /{application}-{profile}.properties
    • /{label}/{application}-{profile}.properties

    Config客户端配置与测试

    1. Module,cloud-config-client-3355

    2. POM

      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-config</artifactId>
      </dependency>
      
    3. bootstrap.yml

      server:
        port: 3355
      
      spring:
        application:
          name: config-client
        cloud:
          #Config客户端配置
          config:
            label: master #分支名称
            name: configclient #配置文件名称
            profile: dev #读取后缀名称   上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
            uri: http://localhost:3344 #配置中心地址
      
      #服务注册到eureka地址
      eureka:
        client:
          service-url:
            defaultZone: http://localhost:7001/eureka
      

      application.yml 是用户级的资源配置项

      bootstrap.yml 是系统级的,优先级更高

      Spring Cloud 会创建一个 Bootstrap Context,作为 Application Context 的父上下文。初始化的时候,Bootstrap Context 负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的 Environment。

      Bootstrap 属性有高优先级,默认情况下,它们不会被本地覆盖。Bootstrap Context 和 Application Context 有着不同的约定,所以新增 bootstrap.yml,保证配置分离。

      bootstrap.yml 先于 application.yml 加载。

    4. 业务类

      @RestController
      public class ConfigClientController {
          @Value("${my.name}")
          private String configInfo;
      
          @GetMapping("/configInfo")
          public String getConfigInfo() {
              return configInfo;
          }
      }
      
    5. 测试,http://localhost:3355/configInfo

      改变Git里配置的内容后,从3344服务端读取到更新后的内容,3355客户端仍然是改变前的内容

    Config客户端之动态刷新

    1. POM

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-actuator</artifactId>
      </dependency>
      
    2. YML

      # 暴露监控端点
      management:
        endpoints:
          web:
            exposure:
              include: "*"
      
    3. 业务类添加注解 @RefreshScope

    4. Git 更改后,发送 Post 请求,localhost:3355/actuator/refresh

  • 相关阅读:
    zabbix短信网关调用问题总结
    zabbix短信接口调用
    Windows Open with Sublime Text
    [转载]windows下安装Python虚拟环境virtualenvwrapper-win
    Resilio-sync auto restart
    django-orm-standalone
    RabbitMQ笔记
    RabbitMQ启动出错:- unable to connect to epmd on xxxx: timeout (timed out)
    [Python笔记]第十六篇:web框架之Tornado
    [前端笔记]第三篇:JavaScript
  • 原文地址:https://www.cnblogs.com/huangwenjie/p/12942390.html
Copyright © 2020-2023  润新知