背景
对于企业而言,不管是传统行业还是互联网,都会有搜索的需求。作为一种一种高效的信息查找方式,随着大数据的到来,如何从海量数据中快速找出中意的信息也越来越重要,本人曾经用过ES做过些项目,对于ES的使用就不做介绍,主要记录下阅读ES的一些源码的体验。
-
插件机制
Elasticsearch的功能是通过可插拔的插件机制来扩充的,在es的源码目录inject中,通过定义一些插件接口来实现插件的扫描和加载。es中的插件大致分为两类:java插件和site插件。 -
插件机制的工作原理
模块作为可插拔的形式在节点启动时进行启动,来以便接收客户端的请求。ES中的模块是一个Guice组件,用来配置信息并且为各式接口绑定一个实现。在InternalNode中有以下代码
'''
//节点的初始化
ModulesBuilder modules = new ModulesBuilder();
modules.add(new Version.Module(version));
modules.add(new CacheRecyclerModule(settings));
modules.add(new PageCacheRecyclerModule(settings));
modules.add(new PluginsModule(settings, pluginsService));
modules.add(new SettingsModule(settings));
modules.add(new NodeModule(this));
modules.add(new NetworkModule());
modules.add(new NodeCacheModule(settings));
modules.add(new ScriptModule(settings));
modules.add(new EnvironmentModule(environment));
modules.add(new NodeEnvironmentModule(nodeEnvironment));
modules.add(new ClusterNameModule(settings));
modules.add(new ThreadPoolModule(settings));
modules.add(new DiscoveryModule(settings));
modules.add(new ClusterModule(settings));
modules.add(new RestModule(settings));
modules.add(new TransportModule(settings));
if (settings.getAsBoolean("http.enabled", true)) {
modules.add(new HttpServerModule(settings));
}
modules.add(new RiversModule(settings));
modules.add(new IndicesModule(settings));
modules.add(new SearchModule());
modules.add(new ActionModule(false));
modules.add(new MonitorModule(settings));
modules.add(new GatewayModule(settings));
modules.add(new NodeClientModule());
modules.add(new BulkUdpModule());
modules.add(new ShapeModule());
modules.add(new PercolatorModule());
modules.add(new ResourceWatcherModule());
modules.add(new RepositoriesModule());
modules.add(new TribeModule());
//节点的启动
injector.getInstance(Discovery.class).setAllocationService(injector.getInstance(AllocationService.class));
for (Class plugin : pluginsService.services()) {
//启动插件(核心位置)
injector.getInstance(plugin).start();
}
//启动索引服务
injector.getInstance(IndicesService.class).start();
injector.getInstance(IndexingMemoryController.class).start();
injector.getInstance(IndicesClusterStateService.class).start();
injector.getInstance(IndicesTTLService.class).start();
injector.getInstance(RiversManager.class).start();
injector.getInstance(ClusterService.class).start();
injector.getInstance(RoutingService.class).start();
injector.getInstance(SearchService.class).start();
injector.getInstance(MonitorService.class).start();
injector.getInstance(RestController.class).start();
injector.getInstance(TransportService.class).start();
DiscoveryService discoService = injector.getInstance(DiscoveryService.class).start();
// gateway should start after disco, so it can try and recovery from gateway on "start"
injector.getInstance(GatewayService.class).start();
'''swift
可看到,在InternalNode的start方法中一次启动各种服务。
-
InternalNode首先添加各个模块的信息
-
创建一个Injector,简单来说就是可以快速和创建很多实例的对象(因为维护了moduled的配置信息),Injector将会使用模块的信息来查找毅力,创建一个有序的top。
-
如何解耦
在es中,设计了一个http层,通过实现http服务器处理各种请求,达到各种组件之间的解耦。采用http层主要考虑到性能等因素,事实上Sonian发布了一个机遇Jetty的http层,基于jetty的实现可以实现authentication。 -
namespace

ES在没有任何插件的情况下,有100多个mudole。这些module是按照namespace来组织的,比如rest inrerface, plugins, rivers是单独的实体,没有模块级别的依赖,这样避免模块太过庞大,提高小模块的复用率。
- 扩展性
大多数模块通过为类或接口提供bindings来达到扩展,其实也可以覆盖内置的功能,然后修改elasticsearch.yml。比如AnalysisModule,通常会根据需要来定制化开发分析器,分析器以及过滤器。
网友评论