故障隔离实现方式
- 容器化:使用 Docker 等容器技术,将每个微服务隔离在独立的容器中,这样一个容器内的故障不会直接影响其他容器。每个容器有自己独立的运行环境,包括操作系统、进程空间等。
- 独立部署:每个微服务部署在独立的服务器或虚拟机上,避免因服务器资源竞争导致一个服务故障影响其他服务。可以根据微服务的资源需求灵活分配服务器资源。
- 资源限制:对每个微服务的资源(如 CPU、内存、网络带宽)进行限制。例如,在 Kubernetes 中,可以通过设置
requests
和 limits
来限制容器对 CPU 和内存的使用,防止某个服务因资源耗尽而拖垮整个系统。
常见容错模式
熔断
- 原理:熔断器监控服务调用的健康状况,当失败率达到一定阈值(如连续 10 次调用中有 8 次失败),熔断器就会打开,后续请求不再发送到实际服务,而是直接返回一个预设的 fallback 响应,避免无效请求持续占用资源。一段时间后(如 10 秒),熔断器进入半开状态,允许少量请求通过,若这些请求成功,熔断器关闭,恢复正常调用;若仍失败,熔断器再次打开。
- 应用场景:适用于依赖的外部服务不稳定,可能出现高延迟或频繁失败的场景。例如,调用第三方支付接口时,如果接口不稳定,使用熔断模式可以防止系统因等待支付接口响应而长时间阻塞。
- 具体实现:在 Java 中,Hystrix 是常用的实现熔断的库。通过在方法上使用
@HystrixCommand
注解,并指定 fallback 方法,如:
@HystrixCommand(fallbackMethod = "paymentFallback")
public String makePayment() {
// 调用第三方支付接口的代码
}
public String paymentFallback() {
// 熔断后的 fallback 处理逻辑
return "支付服务暂时不可用,请稍后重试";
}
限流
- 原理:通过限制单位时间内进入系统或服务的请求数量,防止因请求过多导致系统资源耗尽。常见的限流算法有令牌桶算法和漏桶算法。令牌桶算法是系统以固定速率生成令牌放入桶中,请求到达时从桶中获取令牌,若桶中无令牌则拒绝请求;漏桶算法是请求像水一样流入桶中,以固定速率流出,多余的水(请求)溢出(被拒绝)。
- 应用场景:适用于防止恶意请求、保护系统免受突发流量冲击。例如,对于一些 API 接口,为防止被恶意刷接口,限制每个 IP 每分钟只能请求 100 次。
- 具体实现:在 Spring Boot 中,可以使用 RateLimiter 实现限流。以下是基于令牌桶算法的示例:
import com.google.common.util.concurrent.RateLimiter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ApiController {
private final RateLimiter rateLimiter = RateLimiter.create(10); // 每秒生成 10 个令牌
@GetMapping("/api")
public String api() {
if (rateLimiter.tryAcquire()) {
// 处理请求
return "请求成功";
} else {
return "请求过于频繁,请稍后重试";
}
}
}
重试
- 原理:当服务调用失败时,按照一定的策略(如固定间隔时间、指数退避等)重新发起调用,期望在后续的尝试中成功。固定间隔时间重试是每次重试间隔固定时间,如每次间隔 1 秒;指数退避重试是每次重试间隔时间呈指数增长,如第一次间隔 1 秒,第二次间隔 2 秒,第三次间隔 4 秒等,以避免瞬间大量重试请求对系统造成更大压力。
- 应用场景:适用于因网络抖动、短暂的服务不可用等临时性故障导致的调用失败。例如,在调用数据库查询数据时,偶尔出现网络闪断导致查询失败,此时可以重试。
- 具体实现:在 Java 中,RetryTemplate 是 Spring Retry 提供的重试工具。示例如下:
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Service;
@Service
@EnableRetry
public class DatabaseService {
private final RetryTemplate retryTemplate;
public DatabaseService() {
this.retryTemplate = new RetryTemplate();
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(1000); // 初始间隔 1 秒
backOffPolicy.setMultiplier(2); // 间隔时间翻倍
backOffPolicy.setMaxInterval(10000); // 最大间隔 10 秒
retryTemplate.setBackOffPolicy(backOffPolicy);
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(3); // 最大重试 3 次
retryTemplate.setRetryPolicy(retryPolicy);
}
public String queryData() {
return retryTemplate.execute(context -> {
// 调用数据库查询数据的代码
// 如果失败,会根据设置的策略重试
return "查询结果";
});
}
}