Netflix Hystrix 实现限流主要是通过线程池隔离和信号量隔离两种方式。、
线程池隔离限流
线程池隔离是 Hystrix 的核心功能之一,它通过为每个依赖服务创建一个独立的线程池来隔离依赖服务的调用。这样可以防止一个依赖服务的延迟或失败影响到其他服务的调用。
源码解析:
- HystrixCommand 或 HystrixObservableCommand 的执行:
public abstract class HystrixCommand extends AbstractCommand implements HystrixExecutable, HystrixInvokableInfo {
// ...
protected abstract R run() throws Exception;
// ...
}
在执行 HystrixCommand 时,会调用 run() 方法。这个方法是在 Hystrix 管理的线程池中执行的。
- 线程池的创建和配置:
public abstract class HystrixConcurrencyStrategy {
// ...
public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties threadPoolProperties) {
// 创建线程池的逻辑
}
// ...
}
HystrixConcurrencyStrategy 负责创建和管理线程池。通过 HystrixThreadPoolProperties 可以配置线程池的大小、队列大小等参数,从而实现限流。
- 线程池执行任务:
public class HystrixThreadPool {
// ...
public void execute(Runnable command) {
// 提交任务到线程池执行
}
// ...
}
当 HystrixCommand 被执行时,它会被包装成一个 Runnable 并提交到对应的线程池中执行。
信号量隔离限流
信号量隔离是另一种轻量级的隔离方式,它不使用线程池,而是通过计数信号量来限制对依赖服务的并发调用数量。
源码解析:
- 信号量的创建和配置:
public class HystrixCommandProperties {
// ...
public Integer getProperty(HystrixProperty property, Integer defaultValue) {
// 获取信号量大小配置
}
// ...
}
通过 HystrixCommandProperties 可以配置信号量的大小。
- 信号量执行任务:
public abstract class AbstractCommand implements HystrixInvokableInfo {
// ...
protected final HystrixSemaphore semaphore = new HystrixSemaphore(new SemaphoreCommandHook(), properties semaphorePropertiesDefaults);
// ...
protected final TryableSemaphore getExecutionSemaphore() {
// 返回信号量对象
}
// ...
}
在执行命令之前,会尝试获取信号量。如果信号量已满,则拒绝执行,从而实现限流。
public class TryableSemaphoreActual implements TryableSemaphore {
// ...
public boolean tryAcquire() {
// 尝试获取信号量
}
// ...
}
TryableSemaphoreActual 是信号量的具体实现,tryAcquire() 方法用于尝试获取信号量。
总结
Hystrix 通过线程池和信号量两种方式实现限流,其中线程池隔离提供了更全面的隔离机制,但开销较大;信号量隔离开销较小,但隔离效果不如线程池。开发者可以根据具体需求选择合适的隔离策略。上述源码仅为 Hystrix 实现限流的一部分,实际的源码更复杂,包含了更多的配置和逻辑处理。
Tags:hystrix