隔离机制用来对下游服务最大并发数量的限制
Resilience4j的隔离机制有两种
- 信号量舱壁(SemaphoreBulkhead)
- 固定线程池舱壁(FixedThreadPoolBulkhead)
信号量舱壁
信号量舱壁(SemaphoreBulkhead)原理
当信号量有空闲时,进入系统的请求会直接获取信号量并开始业务处理。
当信号量全被占用时,接下来的请求将会进入阻塞状态,SemaphoreBulkhead提供了一个阻塞计时器,
如果阻塞状态的请求在阻塞计时内无法获取到信号量则系统会拒绝这些请求。
若请求在阻塞计时内获取到了信号量,那将直接获取信号量并执行相应的业务处理。
如何配置信号量隔离
- 引入依赖
<!--resilience4j-bulkhead-->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-bulkhead</artifactId>
</dependency>
- 添加yaml配置
####resilience4j bulkhead 的例子
resilience4j:
bulkhead:
configs:
default:
maxConcurrentCalls: 2 # 隔离允许并发线程执行的最大数量
maxWaitDuration: 1s # 当达到并发调用数量时,新的线程的阻塞时间,我只愿意等待1秒,过时不候进舱壁兜底fallback
instances:
cloud-payment-service:
baseConfig: default
timelimiter:
configs:
default:
timeout-duration: 20s
- 修改业务类
业务类方法上添加注解,name表示服务名称,fallbackMethod 表示降级方法,type表示舱壁类型
@Bulkhead(name = "cloud-payment-service",fallbackMethod = "myBulkheadFallback",type = Bulkhead.Type.SEMAPHORE)
业务类中添加降级方法
public String myBulkheadFallback(Throwable t)
{
return "myBulkheadFallback,隔板超出最大数量限制,系统繁忙,请稍后再试-----/(ㄒoㄒ)/~~";
}
完成配置,当配置如上时,如果有两个请求一直占用服务,则当第三个即以后的请求进来时,等待1秒钟,如果在这一秒钟占用的两个请求有释放的,则当前等待请求进行正常处理业务,没有释放的话则自动进行服务降级处理。
固定线程池舱壁
固定线程池舱壁(FixedThreadPoolBulkhead)
FixedThreadPoolBulkhead的功能与SemaphoreBulkhead一样也是用于限制并发执行的次数的,但是二者的实现原理存在差别而且表现效果也存在细微的差别。FixedThreadPoolBulkhead使用一个固定线程池和一个等待队列来实现舱壁。
当线程池中存在空闲时,则此时进入系统的请求将直接进入线程池开启新线程或使用空闲线程来处理请求。
当线程池中无空闲时时,接下来的请求将进入等待队列,
若等待队列仍然无剩余空间时接下来的请求将直接被拒绝,
在队列中的请求等待线程池出现空闲时,将进入线程池进行业务处理。
另外:ThreadPoolBulkhead只对CompletableFuture方法有效,所以我们必创建返回CompletableFuture类型的方法
如何配置固定线程池舱壁
- 引入依赖
<!--resilience4j-bulkhead-->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-bulkhead</artifactId>
</dependency>
- 修改yaml文件
####resilience4j bulkhead -THREADPOOL的例子
resilience4j:
timelimiter:
configs:
default:
timeout-duration: 10s #timelimiter默认限制远程1s,超过报错不好演示效果所以加上10秒
thread-pool-bulkhead:
configs:
default:
core-thread-pool-size: 1
max-thread-pool-size: 1
queue-capacity: 1
instances:
cloud-payment-service:
baseConfig: default
同时spring.cloud.openfeign.circuitbreaker.group.enabled 请设置为false 新启线程和原来主线程脱离
- 修改业务类的方法
添加注解
@Bulkhead(name = "cloud-payment-service",fallbackMethod = "myBulkheadPoolFallback",type = Bulkhead.Type.THREADPOOL)
修改方法的返回值为CompletableFuture<>类型自己按自己业务需求指定泛型。
添加服务降级的方法
public CompletableFuture<String> myBulkheadPoolFallback(Integer id,Throwable t)
{
return CompletableFuture.supplyAsync(() -> "Bulkhead.Type.THREADPOOL,系统繁忙,请稍后再试-----/(ㄒoㄒ)/~~");
}