elasticsearch的线程池实现在org.elasticsearch.threadpool下。
初始化过程中会加载以threadpool开头的配置项的配置信息,然后确定各个线程池的大小,默认情况下,会参照处理器个数进行设置:
int availableProcessors = EsExecutors.boundedNumberOfProcessors(settings);
int halfProcMaxAt5 = Math.min(((availableProcessors + 1) / 2), 5);
int halfProcMaxAt10 = Math.min(((availableProcessors + 1) / 2), 10);
其中像INDEX/BULK/GET/SUGGEST/PERCOLATOR等这些线程池的大小都设置成了availableProcessor
SEARCH线程池大小设置为availableProcessor*3
而FLUSH/SNAPSHOT/OPTIMIZE等这些线程池大小设置成halfProcMaxAt5
REFRESH线程池则设置成halpProcMaxAt10.
elasticsearch对threadpool的设置思路是相当合理的,一个核对应一个线程,减少context switch。而且,对象FLUSH等这些线程池的大小也做了限制。
根据这些设置生成executor了。
线程池分为cache fix scaling三类,具体设置不再解释,可以了解下java的线程池相关知识。
除了es固定的线程池之外,还可以自定义线程池。
当然,以上默认值都可以在设置中进行更改,build方法的接口就说明了这一点:
private ExecutorHolder build(String name, @Nullable Settings settings, Settings defaultSettings) {
return rebuild(name, null, settings, defaultSettings);
}
其中defaultSetting是上边线程池的默认设置,而settinng则是从配置文件中加载的信息,最终会以setting的设置为准。
build会调用rebuild函数去创建ExecutorHolder,其中SAME的thread是不能更改的,然后依次对cache fix scaling进行对应的设置。
从rebuild的函数接口就可以看出,rebuild不仅仅用于创建(第二个参数设置为null),还用于更新线程池的信息。
stat会得到当前各个线程池的统计信息。
除了以上固有线程,还注册了一个定期执行器:
this.scheduler = new ScheduledThreadPoolExecutor(1, EsExecutors.daemonThreadFactory(settings, "scheduler"), new EsAbortPolicy());
可以通过以下接口在其他模块注册执行的对象:
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, TimeValue interval) {
return scheduler.scheduleWithFixedDelay(new LoggingRunnable(command), interval.millis(), interval.millis(), TimeUnit.MILLISECONDS);
}
比如在SearchService模块中,有如下注册代码:
this.keepAliveReaper = threadPool.scheduleWithFixedDelay(new Reaper(), keepAliveInterval);
总体来看,elasticsearch提供的线程池模块是对java threadpool的进一步封装,如果对java的threadpool比较熟悉的话,这个模块还是比较容易理解。