目录
服务断路器_Resilience4j重试机制
服务断路器_Resilience4j异常比例熔断降级
服务断路器_Resilience4j慢调用比例熔断降级
服务断路器_Resilience4j信号量隔离实现
服务断路器_Resilience4j线程池隔离实现
服务断路器_Resilience4j限流
服务网关Gateway_微服务中的应用
为什么要使用服务网关
服务断路器_Resilience4j重试机制

重试机制比较简单,当服务端处理客户端请求异常时,服务端将会开启重试机制,重试期间内,服务端将每隔一段时间重试业务逻辑处理。 如果最大重试次数内成功处理业务,则停止重试,视为处理成功。如果在最大重试次数内处理业务逻辑依然异常,则此时系统将拒绝该请求。
修改YML文件
resilience4j:
 retry:
   instances:
     backendA:
        # 最大重试次数
       maxRetryAttempts: 3
        # 固定的重试间隔
       waitDuration: 10s
       enableExponentialBackoff: true
       exponentialBackoffMultiplier: 2 
服务提供者新增controller方法
/**
* 重试机制
* @return
*/
@GetMapping("/retry")
@Retry(name = "backendA")
public CompletableFuture<String> retry() {
        log.info("********* 进入方法 ******");
        //异步操作
        CompletableFuture<String> completableFuture = CompletableFuture
               .supplyAsync((Supplier<String>) () -> (paymentFeignService.index()));
        log.info("********* 离开方法 ******");
        return completableFuture;
   } 
服务断路器_Resilience4j异常比例熔断降级
给coud-consumer-feign-order80添加resilience4j依赖
修改yml文件
resilience4j.circuitbreaker:
 configs:
   default:
      # 熔断器打开的失败阈值
     failureRateThreshold: 30
      # 默认滑动窗口大小,circuitbreaker使用基于计数和时间范围欢动窗口聚合统计失败率
     slidingWindowSize: 10
      # 计算比率的最小值,和滑动窗口大小去最小值,即当请求发生5次才会计算失败率
     minimumNumberOfCalls: 5
      # 滑动窗口类型,默认为基于计数的滑动窗口
     slidingWindowType: TIME_BASED
      # 半开状态允许的请求数
     permittedNumberOfCallsInHalfOpenState: 3
      # 是否自动从打开到半开
     automaticTransitionFromOpenToHalfOpenEnabled: true
      # 熔断器从打开到半开需要的时间
     waitDurationInOpenState: 2s
     recordExceptions:
       - java.lang.Exception
 instances:
   backendA:
     baseConfig: default 
编写OrderController
/**
* 异常比例熔断降级
* @return
*/
@GetMapping("/citcuitBackend")
@CircuitBreaker(name = "backendA")
public String citcuitBackend(){
        log.info("************ 进入方法***********");
        String index = paymentFeignService.index();
        log.info("************ 离开方法***********");
        return index;
} 
使用JMeter进行压力测试
修改语言

创建线程组

创建取样器HTTP请求
 
添加查看结果树

修改线程数量

修改HTTP请求参数

半开状态只有三次请求

编写降级方法
/**
* 异常比例熔断降级
* @return
*/
@GetMapping("/citcuitBackend")
@CircuitBreaker(name = "backendA")
public String citcuitTest(){
        log.info("************ 进入方法***********");
        String index =paymentFeignService.index();
        log.info("************ 离开方法***********");
        return index;
   }  
/**
     * 服务降级方法
     * @param e
     * @return
     */
    public String fallback(Throwable e){
        e.printStackTrace();
            return "客官服务繁忙,稍等一会。。。。";
   } 

测试降级方法
1 关闭服务提供者
2 服务消费者发起请求
产生服务降级
 
服务断路器_Resilience4j慢调用比例熔断降级
编写OrderController
    /**
     * 慢调用比例熔断降级
     * @return
     */
    @GetMapping("/slowcircuitbackend")
    @CircuitBreaker(name = "backendB",fallbackMethod = "slowfallback")
    public String slowcircuitbackend(){
        log.info("************ 进入方法***********");
        try {
            TimeUnit.SECONDS.sleep(10);
       } catch (InterruptedException e) {
            e.printStackTrace();
       }
        String index = paymentFeignService.index();
        log.info("************ 离开方法***********");
        return index;
   } 
编写yml文件
resilience4j.circuitbreaker:
 configs:
   default:
            # 熔断器打开的失败阈值
     failureRateThreshold: 30
      # 默认滑动窗口大小,circuitbreaker使用基于计数和时间范围欢动窗口聚合统计失败率
     slidingWindowSize: 10
      # 计算比率的最小值,和滑动窗口大小去最小值,即当请求发生5次才会计算失败率
     minimumNumberOfCalls: 5
      # 滑动窗口类型,默认为基于计数的滑动窗口
     slidingWindowType: TIME_BASED
      # 半开状态允许的请求数
     permittedNumberOfCallsInHalfOpenState: 3
      # 是否自动从打开到半开
     automaticTransitionFromOpenToHalfOpenEnabled: true
      # 熔断器从打开到半开需要的时间
     waitDurationInOpenState: 2s
     recordExceptions:
       - java.lang.Exception
 instances:
   backendA:
     baseConfig: default
   backendB:
      # 熔断器打开的失败阈值
     failureRateThreshold: 50
      # 慢调用时间阈值 高于这个阈值的
     slowCallDurationThreshold: 2s
      # 慢调用百分比阈值,断路器吧调用事件大于slow
     slowCallRateThreshold: 30
     slidingWindowSize: 10
     slidingWindowType: TIME_BASED
     minimumNumberOfCalls: 2
     permittedNumberOfCallsInHalfOpenState:2
     waitDurationInOpenState: 2s
     eventConsumerBufferSize: 10 
服务断路器_Resilience4j信号量隔离实现

POM引入依赖
<dependency>
     <groupId>io.github.resilience4j</groupId>
     <artifactId>resilience4j-bulkhead</artifactId>
     <version>1.7.0</version>
</dependency> 
信号量隔离修改YML文件
resilience4j:
  #信号量隔离
 bulkhead:
   instances:
     backendA:
        # 隔离允许并发线程执行的最大数量
       maxConcurrentCalls: 5
        # 当达到并发调用数量时,新的线程的阻塞时间
       maxWaitDuration: 20ms 
编写controller
/**
     * 测试信号量隔离
     * @return
     */
    @Bulkhead(name = "backendA",type = Bulkhead.Type.SEMAPHORE)
    @GetMapping("bulkhead")
    public String bulkhead() throws InterruptedException {
        log.info("************** 进入方法*******");
        TimeUnit.SECONDS.sleep(10);
        String index = paymentOpenFeignService.index();
        log.info("************** 离开方法*******");
        return index;
   } 
测试
配置隔离并发线程最大数量为5

服务断路器_Resilience4j线程池隔离实现

线程池隔离配置修改YML文件
resilience4j:
 thread-pool-bulkhead:  
   instances:
     backendA:
         # 最大线程池大小
       maxThreadPoolSize: 4
        # 核心线程池大小
       coreThreadPoolSize: 2
        # 队列容量
       queueCapacity: 2 
编写controller
    /**
     * 测试线程池服务隔离
     * @return
     */
    @Bulkhead(name = "backendA",type = Bulkhead.Type.THREADPOOL)
    @GetMapping("/futrue")
    public CompletableFuture  future(){
        log.info("********** 进入方法*******");
        try {
            TimeUnit.SECONDS.sleep(5);
       } catch (InterruptedException e) {
            e.printStackTrace();
       }
        log.info("********** 离开方法*******");
        return CompletableFuture.supplyAsync(() -> "线程池隔离信息......");
   } 
测试
配置文件设置核心线程2个最大4个服务会一次处理4个请求

服务断路器_Resilience4j限流
限流YML配置
ratelimiter:
   instances:
     backendA:
        # 限流周期时长。       默认:500纳秒
       limitRefreshPeriod: 5s
        # 周期内允许通过的请求数量。     默认:50
       limitForPeriod: 2 
先写Controller
    /**
     * 限流
     * @return
     */
    @GetMapping("/limiter")
    @RateLimiter(name = "backendA")
    public CompletableFuture<String> RateLimiter() {
        log.info("********* 进入方法 ******");
        //异步操作
        CompletableFuture<String> completableFuture = CompletableFuture
               .supplyAsync((Supplier<String>) () ->(paymentFeignService.index()));
        log.info("********* 离开方法 ******");
        return completableFuture;
   } 
JMeter压测
线程数 - 5
 
服务网关Gateway_微服务中的应用

没有服务网关

问题:
1 地址太多
2 安全性
3 管理问题
为什么要使用服务网关

网关是微服务架构中不可或缺的部分。使用网关后,客户端和微服务之间的网络结构如下。
 
注意: 网关统一向外部系统(如访问者、服务)提供REST API。在 SpringCloud 中,使用Zuul、Spring Cloud Gateway等作为API Gateway来实现动态路由、监控、回退、安全等功能。
认识Spring Cloud Gateway
Spring Cloud Gateway 是 Spring Cloud生态系统中的网关,它是基于Spring 5.0、SpringBoot 2.0和Project Reactor等技术开发的, 旨在为微服务架构提供一种简单有效的、统一的API路由管理方式, 并为微服务架构提供安全、监控、指标和弹性等功能。其目标是替代Zuul。
 
注意: Spring Cloud Gateway 用"Netty + Webflux"实现,不要加入 Web依赖,否则会报错,它需要加入Webflux依赖。
什么是WebFlux
Webflux模式替换了旧的Servlet线程模型。用少量的线程处理 request和response io操作,这些线程称为Loop线程,而业务交给响应式编程框架处理,响应式编程是非常灵活的,用户可以将业务中阻塞的操作提交到响应式框架的work线程中执行,而不阻塞的操作依然可以在Loop线程中进行处理,大大提高了Loop线程的利用 率。
 
注意:
Webflux虽然可以兼容多个底层的通信框架,但是一般情况下, 底层使用的还是Netty,毕竟,Netty是目前业界认可的最高性能的通信框架。而Webflux的Loop线程,正好就是著名的 Reactor模式IO处理模型的Reactor线程,如果使用的是高性能的通信框架Netty。
温馨提示:
什么是Netty,Netty 是一个基于NIO的客户、服务器端的编程 框架。提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
Spring Cloud Gateway特点
1、易于编写谓词( Predicates )和过滤器( Filters ) 。其Predicates和Filters可作用于特定路由。
2、支持路径重写。
3、支持动态路由。
4、集成了Spring Cloud DiscoveryClient。
实时效果反馈
1.Spring Cloud Gateway 是 Spring Cloud生态系统中的_____。
A 断路器
B 注册发现服务
C 网关
D 以上都不是
2.下列不属于服务网关Gateway特点得是____。
A 支持路径重写
B 支持动态路由
C 服务熔断
D 集成服务发现




















