服务与服务之间的依赖性,故障会传播,造成连锁反应,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。
造成雪崩原因是什么
注意:
在高并发访问下,系统所依赖的服务的稳定性对系统的影响非常大,依赖有很多不可控的因素,比如网络连接变慢,资源突然繁忙,暂时不可用,服务脱机等。我们要构建稳定、可靠的分布式系统,就必须要有一套容错方法。
什么是熔断?
熔断就跟保险丝一样,当一个服务请求并发特别大,服务器已经招架不住了,调用错误率飙升,当错误率达到一定阈值后,就将这个服务熔断了。熔断之后,后续的请求就不会再请求服务器了,以减缓服务器的压力
注意:
**两种场景: **
**服务降级 fallback **
概念:服务器繁忙,请稍后重试,不让客户端等待并立即返回一个友好的提示。
出现服务降级的情况
做服务隔离的目的就是避免服务之间相互影响。毕竟谁也不能说自己的微服务百分百可用,如果不做隔离,一旦一个服务出现了问题,整个系统的稳定性都会受到影响! 因此,做服务隔离是很有必要的。
线程池隔离
将用户请求线程和服务执行线程分割开来,同时约定了每个服务最多可用线程数。
信号量隔离
小时候我们就知道“红灯停,绿灯行”,跟着交通信号的指示过马路。信号量也是这么一种放行、禁行的开关作用。它和线程池技术一样,控制了服务可以被同时访问的并发数量。
服务熔断和服务隔离都属于出错后的容错处理机制,而限流模式则可以称为预防模式。
限流模式主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。
**注意: **
限流的目的是通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理。
**流量控制 **
Resilience4j 是一个轻量级的容错库,用于在 Java 8 及更高版本的应用程序中实现容错、限流、重试和熔断等功能。它提供了一种简单而强大的方法来处理分布式系统中的故障和延迟。本文将对 Resilience4j 的主要功能进行总结,包括其核心组件、使用方法和一些高级特性。
Circuit Breaker(熔断器)
熔断器是一种保护机制,用于防止系统在出现故障时继续尝试执行操作。当一个服务连续失败达到一定次数时,熔断器会打开,后续请求将直接返回错误,而不是继续尝试调用服务。当服务恢复正常后,熔断器会自动关闭。**Resilience4j 有异常比例熔断降级和慢调用比例熔断降级。**异常比例熔断注重请求异常的比例,慢调用注重请求超时异常的比重。
Resilience4j 提供了 CircuitBreaker 类来实现熔断器功能。以下是一个简单的示例:
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
.failureRateThreshold(50) // 失败率阈值,超过此值熔断器将打开
.waitDurationInOpenState(Duration.ofMillis(100)) // 熔断器打开后的等待时间
.permittedNumberOfCallsInHalfOpenState(2) // 半开状态下允许的调用次数
.slidingWindowSize(10) // 滑动窗口大小
.build();
CircuitBreaker circuitBreaker = CircuitBreaker.of("myCircuitBreaker", circuitBreakerConfig);
Mono<String> result = Mono.defer(() -> {
if (circuitBreaker.isCallPermitted("myCircuitBreaker")) {
return Mono.just("Hello, World!");
} else {
return Mono.error(new RuntimeException("Circuit breaker is open"));
}
});
RateLimiter(限流器)
限流器用于限制系统资源的使用,以防止过载。Resilience4j 提供了 RateLimiter 类来实现限流功能。以下是一个简单的示例:
RateLimiterConfig rateLimiterConfig = RateLimiterConfig.custom()
.limitForPeriod(10) // 每秒允许的请求数量
.limitRefreshPeriod(Duration.ofSeconds(1)) // 刷新周期
.build();
RateLimiter rateLimiter = RateLimiter.of("myRateLimiter", rateLimiterConfig);
Mono<String> result = Mono.defer(() -> {
if (rateLimiter.tryAcquire()) {
return Mono.just("Hello, World!");
} else {
return Mono.error(new RuntimeException("Rate limit exceeded"));
}
});
Retry(重试)
重试是一种策略,用于在操作失败时自动重新尝试执行。Resilience4j 提供了 Retry 类来实现重试功能。以下是一个简单的示例:
RetryConfig retryConfig = RetryConfig.custom()
.maxAttempts(3) // 最大重试次数
.waitDuration(Duration.ofMillis(100)) // 重试之间的等待时间
.retryOnException(e -> e instanceof IOException) // 指定需要重试的异常类型
.build();
Retry retry = Retry.of("myRetry", retryConfig);
Mono<String> result = Mono.defer(() -> {
if (retry.isRetry()) {
return Mono.error(new IOException("Retrying..."));
} else {
return Mono.just("Hello, World!");
}
}).retryWhen(retry);
依赖添加
在项目的 build.gradle 或 pom.xml 文件中添加 Resilience4j 的依赖:
implementation ‘io.github.resilience4j:resilience4j-core:1.7.0’
创建实例
根据需要创建 CircuitBreaker、RateLimiter 或 Retry 的实例,并配置相应的参数。
使用实例
在需要的地方使用创建的实例,例如在调用远程服务或执行可能失败的操作时。
自定义注解
Resilience4j 支持自定义注解,可以更方便地应用到方法上。例如,可以创建一个名为 @Retryable 的注解,并在需要重试的方法上使用它:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Retryable {
int maxAttempts() default 3;
Duration waitDuration() default Duration.ofMillis(100);
Class<? extends Throwable>[] retryOnException() default {};
}
然后在需要重试的方法上添加 @Retryable 注解:
@Retryable(maxAttempts = 3, waitDuration = Duration.ofMillis(100))
public Mono<String> myMethod() {
// ...
}
组合使用
Resilience4j 支持将多个组件组合在一起使用,例如可以将 CircuitBreaker 和 Retry 组合起来,以实现更强大的容错能力。以下是一个简单的示例:
CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("myCircuitBreaker");
Retry retry = Retry.ofDefaults("myRetry");
Mono<String> result = Mono.defer(() -> {
if (circuitBreaker.isCallPermitted("myCircuitBreaker") && retry.isRetry()) {
return Mono.just("Hello, World!");
} else {
return Mono.error(new RuntimeException("Operation failed"));
}
}).retryWhen(retry);
Resilience4j 是一个功能强大且易于使用的容错库,可以帮助我们更好地应对分布式系统中的故障和延迟。通过本文的介绍,相信大家已经对 Resilience4j 的核心组件、使用方法和高级特性有了一定的了解。在实际项目中,可以根据需要选择合适的组件和配置,以提高系统的可靠性和稳定性。
以上就是全部内容,如果你有任何问题、意见或建议,都欢迎在评论中分享。让我们继续分享知识,共同成长,一起走向更加美好的未来。感谢你们的阅读,祝愿你们在未来的道路上一帆风顺!