当前位置: 首页 > news >正文

(三)elasticsearch 源码之启动流程分析

https://www.cnblogs.com/darcy-yuan/p/17007635.html

1.前面我们在《(一)elasticsearch 编译和启动》和 《(二)elasticsearch 源码目录 》简单了解下es(elasticsearch,下同),现在我们来看下启动代码

下面是启动流程图,我们按照流程图的顺序依次描述

2.启动流程

org.elasticsearch.bootstrap.Elasticsearchpublic static void main(final String[] args) throws Exception {overrideDnsCachePolicyProperties();/** We want the JVM to think there is a security manager installed so that if internal policy decisions that would be based on the* presence of a security manager or lack thereof act as if there is a security manager present (e.g., DNS cache policy). This* forces such policies to take effect immediately.*/System.setSecurityManager(new SecurityManager() {@Overridepublic void checkPermission(Permission perm) {// grant all permissions so that we can later set the security manager to the one that we want}});LogConfigurator.registerErrorListener();final Elasticsearch elasticsearch = new Elasticsearch();int status = main(args, elasticsearch, Terminal.DEFAULT);if (status != ExitCodes.OK) {exit(status);}}

后续执行 Elasticsearch.execute -> Elasticsearch.init -> Bootstrap.init

org.elasticsearch.bootstrap.Bootstrapstatic void init(final boolean foreground,final Path pidFile,final boolean quiet,final Environment initialEnv) throws BootstrapException, NodeValidationException, UserException {// force the class initializer for BootstrapInfo to run before// the security manager is installedBootstrapInfo.init();INSTANCE = new Bootstrap();// 安全配置文件final SecureSettings keystore = loadSecureSettings(initialEnv);final Environment environment = createEnvironment(pidFile, keystore, initialEnv.settings(), initialEnv.configFile());LogConfigurator.setNodeName(Node.NODE_NAME_SETTING.get(environment.settings()));try {LogConfigurator.configure(environment);} catch (IOException e) {throw new BootstrapException(e);}if (JavaVersion.current().compareTo(JavaVersion.parse("11")) < 0) {final String message = String.format(Locale.ROOT,"future versions of Elasticsearch will require Java 11; " +"your Java version from [%s] does not meet this requirement",System.getProperty("java.home"));new DeprecationLogger(LogManager.getLogger(Bootstrap.class)).deprecated(message);}// 处理pidFileif (environment.pidFile() != null) {try {PidFile.create(environment.pidFile(), true);} catch (IOException e) {throw new BootstrapException(e);}}// 如果是后台启动,则不打印日志final boolean closeStandardStreams = (foreground == false) || quiet;try {if (closeStandardStreams) {final Logger rootLogger = LogManager.getRootLogger();final Appender maybeConsoleAppender = Loggers.findAppender(rootLogger, ConsoleAppender.class);if (maybeConsoleAppender != null) {Loggers.removeAppender(rootLogger, maybeConsoleAppender);}closeSystOut();}// fail if somebody replaced the lucene jarscheckLucene();// 通用异常捕获// install the default uncaught exception handler; must be done before security is// initialized as we do not want to grant the runtime permission// setDefaultUncaughtExceptionHandlerThread.setDefaultUncaughtExceptionHandler(new ElasticsearchUncaughtExceptionHandler());INSTANCE.setup(true, environment);try {// any secure settings must be read during node constructionIOUtils.close(keystore);} catch (IOException e) {throw new BootstrapException(e);}INSTANCE.start();if (closeStandardStreams) {closeSysError();}}

这里我们可以关注下  INSTANCE.setup(true, environment);

org.elasticsearch.bootstrap.Bootstrapprivate void setup(boolean addShutdownHook, Environment environment) throws BootstrapException {Settings settings = environment.settings();try {spawner.spawnNativeControllers(environment);} catch (IOException e) {throw new BootstrapException(e);}// 检查一些mlock设定initializeNatives(environment.tmpFile(),BootstrapSettings.MEMORY_LOCK_SETTING.get(settings),BootstrapSettings.SYSTEM_CALL_FILTER_SETTING.get(settings),BootstrapSettings.CTRLHANDLER_SETTING.get(settings));// 探针// initialize probes before the security manager is installedinitializeProbes();if (addShutdownHook) {Runtime.getRuntime().addShutdownHook(new Thread() {@Overridepublic void run() {try {IOUtils.close(node, spawner);LoggerContext context = (LoggerContext) LogManager.getContext(false);Configurator.shutdown(context);if (node != null && node.awaitClose(10, TimeUnit.SECONDS) == false) {throw new IllegalStateException("Node didn't stop within 10 seconds. " +"Any outstanding requests or tasks might get killed.");}} catch (IOException ex) {throw new ElasticsearchException("failed to stop node", ex);} catch (InterruptedException e) {LogManager.getLogger(Bootstrap.class).warn("Thread got interrupted while waiting for the node to shutdown.");Thread.currentThread().interrupt();}}});}try {// 检查类加载的一些问题// look for jar hellfinal Logger logger = LogManager.getLogger(JarHell.class);JarHell.checkJarHell(logger::debug);} catch (IOException | URISyntaxException e) {throw new BootstrapException(e);}// Log ifconfig output before SecurityManager is installedIfConfig.logIfNecessary();// 安全处理// install SM after natives, shutdown hooks, etc.try {Security.configure(environment, BootstrapSettings.SECURITY_FILTER_BAD_DEFAULTS_SETTING.get(settings));} catch (IOException | NoSuchAlgorithmException e) {throw new BootstrapException(e);}node = new Node(environment) {@Overrideprotected void validateNodeBeforeAcceptingRequests(final BootstrapContext context,final BoundTransportAddress boundTransportAddress, List<BootstrapCheck> checks) throws NodeValidationException {BootstrapChecks.check(context, boundTransportAddress, checks);}};}

最后一句 node = new Node(environment) 初始化了节点,里面做了许多工作

org.elasticsearch.node.Nodeprotected Node(final Environment environment, Collection<Class<? extends Plugin>> classpathPlugins, boolean forbidPrivateIndexSettings) {...// 打印jvm信息final JvmInfo jvmInfo = JvmInfo.jvmInfo();logger.info("version[{}], pid[{}], build[{}/{}/{}/{}], OS[{}/{}/{}], JVM[{}/{}/{}/{}]",Build.CURRENT.getQualifiedVersion(),jvmInfo.pid(),Build.CURRENT.flavor().displayName(),Build.CURRENT.type().displayName(),Build.CURRENT.hash(),Build.CURRENT.date(),Constants.OS_NAME,Constants.OS_VERSION,Constants.OS_ARCH,Constants.JVM_VENDOR,Constants.JVM_NAME,Constants.JAVA_VERSION,Constants.JVM_VERSION);
...// 初始化各类服务,以及他们相关的依赖this.pluginsService = new PluginsService(tmpSettings, environment.configFile(), environment.modulesFile(),environment.pluginsFile(), classpathPlugins);final Settings settings = pluginsService.updatedSettings();final Set<DiscoveryNodeRole> possibleRoles = Stream.concat(DiscoveryNodeRole.BUILT_IN_ROLES.stream(),pluginsService.filterPlugins(Plugin.class).stream().map(Plugin::getRoles).flatMap(Set::stream)).collect(Collectors.toSet());DiscoveryNode.setPossibleRoles(possibleRoles);localNodeFactory = new LocalNodeFactory(settings, nodeEnvironment.nodeId());
...// guice注入modules.add(b -> {b.bind(Node.class).toInstance(this);b.bind(NodeService.class).toInstance(nodeService);b.bind(NamedXContentRegistry.class).toInstance(xContentRegistry);b.bind(PluginsService.class).toInstance(pluginsService);b.bind(Client.class).toInstance(client);b.bind(NodeClient.class).toInstance(client);b.bind(Environment.class).toInstance(this.environment);b.bind(ThreadPool.class).toInstance(threadPool);

es 使用 guice注入框架,guice是个非常轻量级的依赖注入框架,既然各个组件都已经注入好了,我们现在可以启动了。

INSTANCE.start -> Bootstrap.start

org.elasticsearch.bootstrap.Bootstrapprivate void start() throws NodeValidationException {node.start();keepAliveThread.start();}

 node.start中启动各个组件。es中的各个组件继承了 AbstractLifecycleComponent。start方法会调用组件的doStart方法。

org.elasticsearch.node.Nodepublic Node start() throws NodeValidationException {if (!lifecycle.moveToStarted()) {return this;}logger.info("starting ...");pluginLifecycleComponents.forEach(LifecycleComponent::start);injector.getInstance(MappingUpdatedAction.class).setClient(client);injector.getInstance(IndicesService.class).start();injector.getInstance(IndicesClusterStateService.class).start();injector.getInstance(SnapshotsService.class).start();injector.getInstance(SnapshotShardsService.class).start();injector.getInstance(SearchService.class).start();nodeService.getMonitorService().start();final ClusterService clusterService = injector.getInstance(ClusterService.class);final NodeConnectionsService nodeConnectionsService = injector.getInstance(NodeConnectionsService.class);nodeConnectionsService.start();clusterService.setNodeConnectionsService(nodeConnectionsService);...

具体的我们看两个比较重要的服务  transportService.start();

org.elasticsearch.transport.TransportService@Overrideprotected void doStart() {transport.setMessageListener(this);connectionManager.addListener(this);// 建立网络连接transport.start();if (transport.boundAddress() != null && logger.isInfoEnabled()) {logger.info("{}", transport.boundAddress());for (Map.Entry<String, BoundTransportAddress> entry : transport.profileBoundAddresses().entrySet()) {logger.info("profile [{}]: {}", entry.getKey(), entry.getValue());}}localNode = localNodeFactory.apply(transport.boundAddress());if (connectToRemoteCluster) {// here we start to connect to the remote clustersremoteClusterService.initializeRemoteClusters();}}

启动transport的实现类是 SecurityNetty4HttpServerTransport

 另一个比较重要的服务,discovery.start(),具体实现类是 Coordinator

org.elasticsearch.cluster.coordination.Coordinator@Overrideprotected void doStart() {synchronized (mutex) {CoordinationState.PersistedState persistedState = persistedStateSupplier.get();coordinationState.set(new CoordinationState(getLocalNode(), persistedState, electionStrategy));peerFinder.setCurrentTerm(getCurrentTerm());configuredHostsResolver.start();final ClusterState lastAcceptedState = coordinationState.get().getLastAcceptedState();if (lastAcceptedState.metaData().clusterUUIDCommitted()) {logger.info("cluster UUID [{}]", lastAcceptedState.metaData().clusterUUID());}final VotingConfiguration votingConfiguration = lastAcceptedState.getLastCommittedConfiguration();if (singleNodeDiscovery &&votingConfiguration.isEmpty() == false &&votingConfiguration.hasQuorum(Collections.singleton(getLocalNode().getId())) == false) {throw new IllegalStateException("cannot start with [" + DiscoveryModule.DISCOVERY_TYPE_SETTING.getKey() + "] set to [" +DiscoveryModule.SINGLE_NODE_DISCOVERY_TYPE + "] when local node " + getLocalNode() +" does not have quorum in voting configuration " + votingConfiguration);}...

相关文章:

  • 时序预测 | MATLAB实现基于CNN-LSTM-AdaBoost卷积长短期记忆网络结合AdaBoost时间序列预测
  • Flask实现文件下载服务的优雅实现
  • RabbitMQ-3.发送者的可靠性
  • 机器学习11-前馈神经网络识别手写数字1.0
  • AutoSAR(基础入门篇)5.4-Autosar_汽车ECU项目的开发流程
  • 深入了解RocketMQ消息中间件:架构、特性和应用场景
  • ag-Grid:对数据变化的单元格进行高亮显示
  • 论文阅读——MP-Former
  • RabbitMQ-2.SpringAMQP
  • CSS高级技巧
  • SegmentAnything官网demo使用vue+python实现
  • 计算机网络总结
  • 2024/2/4 备战蓝桥杯 5-1 前缀和
  • mac检查CPU温度和风扇速度软件:Macs Fan Control Pro 1.5.17中文版
  • 决策树之scikit-learn
  • JavaScript-如何实现克隆(clone)函数
  • [笔记] php常见简单功能及函数
  • 【347天】每日项目总结系列085(2018.01.18)
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • HTML中设置input等文本框为不可操作
  • Idea+maven+scala构建包并在spark on yarn 运行
  • Java 网络编程(2):UDP 的使用
  • java第三方包学习之lombok
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • PaddlePaddle-GitHub的正确打开姿势
  • Redis学习笔记 - pipline(流水线、管道)
  • storm drpc实例
  • 阿里云应用高可用服务公测发布
  • 回顾2016
  • 基于web的全景—— Pannellum小试
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 如何合理的规划jvm性能调优
  • 什么是Javascript函数节流?
  • 算法-插入排序
  • 源码安装memcached和php memcache扩展
  • HanLP分词命名实体提取详解
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • ​如何在iOS手机上查看应用日志
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • # Panda3d 碰撞检测系统介绍
  • $.ajax中的eval及dataType
  • ( 10 )MySQL中的外键
  • (1)虚拟机的安装与使用,linux系统安装
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (C语言)字符分类函数
  • (二)学习JVM —— 垃圾回收机制
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (转)关于多人操作数据的处理策略
  • (转)为C# Windows服务添加安装程序
  • (转载)Google Chrome调试JS
  • .net core 6 集成和使用 mongodb
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)...
  • .NET处理HTTP请求
  • // an array of int