elasticsearch 원본에서 노드 시작 프로세스 보기
87718 단어 elasticsearch
elasticsearch
노드가 시작되는 대체적인 절차를 이해하고자 한다.1. 구성 읽기 실행 환경 만들기
운영 환경은
Environment
대상을 가리킨다. 이 대상은 Settings
대상(es 설정), data
경로, plugins
경로, modules
경로, bin
경로, libs
경로, log
경로, es.path.conf
경로 등을 봉인했다.관련 소스:
/** Create an {@link Environment} for the command to use. Overrideable for tests. */
protected Environment createEnv(final Terminal terminal, final Map<String, String> settings) throws UserException {
final String esPathConf = System.getProperty("es.path.conf");
if (esPathConf == null) {
throw new UserException(ExitCodes.CONFIG, "the system property [es.path.conf] must be set");
}
return InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, terminal, settings, getConfigPath(esPathConf));
}
여기에서
es.path.conf
의 설정, 즉es의 각종 설정 파일이 있는 경로를 읽을 수 있습니다.개인적으로 여기는
es.home
의 설정을 읽을 필요가 없다고 생각합니다. 이 설정은 실제로 필요 없습니다. 이미 Environment
의 설정이 있고 home
류의 구조 함수에 이런 코드가 있기 때문입니다.Environment(final Settings settings, final Path configPath, final Path tmpPath)
...
if (configPath != null) {
configFile = configPath.normalize();
} else {
configFile = homeFile.resolve("config");
}
...
}
기본 프로필 위치는
config
경로의 elasticsearch.yml
안입니다.Settings
구성 파일의 로드는 다음과 같습니다.public static Environment prepareEnvironment(Settings input, Terminal terminal, Map<String, String> properties, Path configPath) {
...
output = Settings.builder(); // start with a fresh output
Path path = environment.configFile().resolve("elasticsearch.yml");
if (Files.exists(path)) {
try {
output.loadFromPath(path);
} catch (IOException e) {
throw new SettingsException("Failed to load settings from " + path.toString(), e);
}
}
...
return new Environment(output.build(), configPath);
}
불러오는 설정은
Environment
대상으로 봉하여 Node
에 설정합니다.2. 노드 초기화
이 부호는 모두
try
류의 아래 이 구조 함수 안에 있다protected Node(final Environment environment, Collection<Class<? extends Plugin>> classpathPlugins) {
...
logger.info("initializing ...");
...
logger.info("initialized");
...
}
일부 세부 사항을 생략하면 우리가 es를 시작할 때 자주 보는 두 개의 로그를 뚜렷하게 볼 수 있다.
다음은 안의 관건적인 세부 사항을 살펴보고 이 구조 함수를 전체적으로 살펴보자.
protected Node(final Environment environment, Collection<Class<? extends Plugin>> classpathPlugins) {
final List<Closeable> resourcesToClose = new ArrayList<>(); // register everything we need to release in the case of an error
boolean success = false;
{
// use temp logger just to say we are starting. we can't use it later on because the node name might not be set
Logger logger = Loggers.getLogger(Node.class, NODE_NAME_SETTING.get(environment.settings()));
logger.info("initializing ...");
}
try {
...
} catch (IOException ex) {
throw new ElasticsearchException("failed to bind service", ex);
} finally {
if (!success) {
IOUtils.closeWhileHandlingException(resourcesToClose);
}
}
}
구체적인 세부 사항은 이
List
에서 많은 자원을 열 수 있습니다. 이 자원들은 모두 finally
에 추가됩니다. 초기화에 실패하면 try
에서 이 자원을 닫습니다.그리고
Environment
에 들어가서 노드를 구체적으로 초기화하는 절차를 살펴본다.노드 구성
originalSettings = environment.settings();
Settings tmpSettings = Settings.builder().put(environment.settings())
.put(Client.CLIENT_TYPE_SETTING_S.getKey(), CLIENT_TYPE).build();
// create the node environment as soon as possible, to recover the node id and enable logging
try {
nodeEnvironment = new NodeEnvironment(tmpSettings, environment);
resourcesToClose.add(nodeEnvironment);
} catch (IOException ex) {
throw new IllegalStateException("Failed to create node environment", ex);
}
NodeEnvironment
객체의 구성을 읽고 노드 자체 구성을 생성합니다. 이 구성에는 다음과 같은 정보가 포함되지만 이에 국한되지 않습니다.node.max_local_storage_nodes
, 로컬 최대 저장 노드 수량, 기본 1, 즉 로컬 최대 한 개의 데이터를 저장할 수 있는 노드만 동시에 시작할 수 있음;node.id.seed
, 노드 id를 생성하는 무작위 피드, 기본값은 0;indice
데이터 저장 경로, 기본값은 {nodePath}/indices;또한 이 안에는 노드 id를 무작위로 생성하여 디스크, jvm 정보를 읽고 출력했습니다. 이곳의
heap size
은 기본값인 1/4
의 물리적 메모리입니다.[2018-10-19T17:52:35,480][INFO ][o.e.e.NodeEnvironment ] [0aIXj0y] using [1] data paths, mounts [[(F:)]], net usable_space [215gb], net total_space [231gb], types [NTFS]
[2018-10-19T17:53:12,209][INFO ][o.e.e.NodeEnvironment ] [0aIXj0y] heap size [7.9gb], compressed ordinary object pointers [true]
노드 이름 생성
final boolean hadPredefinedNodeName = NODE_NAME_SETTING.exists(tmpSettings);
final String nodeId = nodeEnvironment.nodeId();
tmpSettings = addNodeNameIfNeeded(tmpSettings, nodeId);
node.name
에 설정이 있는지 확인하고 사용자가 설정하지 않으면 nodeId
의 7위를 노드 이름으로 한다.plugins 및 modules 로드
this.pluginsService = new PluginsService(tmpSettings, environment.configFile(), environment.modulesFile(), environment.pluginsFile(), classpathPlugins);
PluginService
의 구조 함수에 모든 plugins
과 modules
을 불러오면 다음과 같은 로그가 출력됩니다.[2018-10-22T15:42:43,978][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [aggs-matrix-stats]
[2018-10-22T15:42:43,980][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [analysis-common]
[2018-10-22T15:42:43,981][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [ingest-common]
[2018-10-22T15:42:43,982][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [lang-expression]
[2018-10-22T15:42:43,983][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [lang-mustache]
[2018-10-22T15:42:43,983][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [lang-painless]
[2018-10-22T15:42:43,984][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [mapper-extras]
[2018-10-22T15:42:43,985][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [parent-join]
[2018-10-22T15:42:43,986][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [percolator]
[2018-10-22T15:42:43,987][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [rank-eval]
[2018-10-22T15:42:43,988][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [reindex]
[2018-10-22T15:42:43,989][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [repository-url]
[2018-10-22T15:42:43,990][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [transport-netty4]
[2018-10-22T15:42:43,991][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [tribe]
[2018-10-22T15:42:43,992][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [x-pack-core]
[2018-10-22T15:42:43,993][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [x-pack-deprecation]
[2018-10-22T15:42:43,994][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [x-pack-graph]
[2018-10-22T15:42:43,994][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [x-pack-logstash]
[2018-10-22T15:42:43,995][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [x-pack-ml]
[2018-10-22T15:42:43,996][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [x-pack-monitoring]
[2018-10-22T15:42:43,998][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [x-pack-rollup]
[2018-10-22T15:42:43,999][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [x-pack-security]
[2018-10-22T15:42:44,000][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [x-pack-sql]
[2018-10-22T15:42:44,001][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [x-pack-upgrade]
[2018-10-22T15:42:44,002][INFO ][o.e.p.PluginsService ] [localhost-debug] loaded module [x-pack-watcher]
[2018-10-22T15:42:45,130][INFO ][o.e.p.PluginsService ] [localhost-debug] no plugins loaded
모듈별 초기화
뒤에 수백 줄에 달하는 코드는 모두 각 모듈과 구성 요소(
AbstractComponent
류)를 구성하고 있다. 예를 들어 ScriptModule
, AnalysisModule
, SearchModule
, IndicesService
, ClusterService
, TransportService
등이다.인쇄 로그는 다음과 같습니다.
[2018-10-24T16:10:08,595][DEBUG][o.e.a.ActionModule ] Using REST wrapper from plugin org.elasticsearch.xpack.security.Security
[2018-10-24T16:10:08,856][INFO ][o.e.d.DiscoveryModule ] [localhost-debug] using discovery type [zen]
각 모듈과 부품이 각각 어떤 기능을 담당하는지는 여기서 잠시 깊이 연구하지 않고 실제로는 유명에 따라 대체적으로 그 작용을 추측할 수 있다.
3. 부팅 노드
이 코드는
Node
류의 start()
방법 안에 있다.구성 요소 시작
/**
* Start the node. If the node is already started, this method is no-op.
*/
public Node start() throws NodeValidationException {
if (!lifecycle.moveToStarted()) {
return this;
}
Logger logger = Loggers.getLogger(Node.class, NODE_NAME_SETTING.get(settings));
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(RoutingService.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);
injector.getInstance(ResourceWatcherService.class).start();
injector.getInstance(GatewayService.class).start();
Discovery discovery = injector.getInstance(Discovery.class);
clusterService.getMasterService().setClusterStatePublisher(discovery::publish);
// Start the transport service now so the publish address will be added to the local disco node in ClusterService
TransportService transportService = injector.getInstance(TransportService.class);
transportService.getTaskManager().setTaskResultsService(injector.getInstance(TaskResultsService.class));
transportService.start();
assert localNodeFactory.getNode() != null;
assert transportService.getLocalNode().equals(localNodeFactory.getNode())
: "transportService has a different local node than the factory provided";
final MetaData onDiskMetadata;
try {
// we load the global state here (the persistent part of the cluster state stored on disk) to
// pass it to the bootstrap checks to allow plugins to enforce certain preconditions based on the recovered state.
if (DiscoveryNode.isMasterNode(settings) || DiscoveryNode.isDataNode(settings)) {
onDiskMetadata = injector.getInstance(GatewayMetaState.class).loadMetaState();
} else {
onDiskMetadata = MetaData.EMPTY_META_DATA;
}
assert onDiskMetadata != null : "metadata is null but shouldn't"; // this is never null
} catch (IOException e) {
throw new UncheckedIOException(e);
}
...
}
이
start
은 많은 구성 요소(Service
, 모두 AbstractComponent
의 하위 클래스)인데 구체적인 논리는 잠시 따지지 않고 로그를 인쇄하면 다음과 같다.[2018-10-24T16:10:16,609][INFO ][o.e.n.Node ] [localhost-debug] starting ...
[2018-10-24T16:11:14,864][INFO ][o.e.t.TransportService ] [localhost-debug] publish_address {xx.xx.xx.xx:9300}, bound_addresses {xx.xx.xx.xx:9300}
node 정보 확인
validateNodeBeforeAcceptingRequests(new BootstrapContext(settings, onDiskMetadata), transportService.boundAddress(), pluginsService
.filterPlugins(Plugin
.class)
.stream()
.flatMap(p -> p.getBootstrapChecks().stream()).collect(Collectors.toList()));
이 코드는
node
에 대해 시작 검증을 하고 로그는 다음과 같다.[2018-10-24T16:33:31,983][INFO ][o.e.b.BootstrapChecks ] [localhost-debug] bound or publishing to a non-loopback address, enforcing bootstrap checks
elasticsearch.yml
에서 network.host
이나 다른 방식(예를 들어 http.host
, transport.host
)의 host
의 설정을 수정했다면 기본적인 127.0.0.1
이 아니라 bootstrap check
에 문제가 발견되면 warning
이 아니라 error
이다.여기에 약간의 문제가 보고될 수 있다.예를 들어 설정-Xms와 -Xmx의 값이 같지 않으면 문제가 생길 수 있고
file descriptors
과 같은 다른 문제도 인터넷에서 해결 방법을 찾을 수 있다.join cluster
discovery.startInitialJoin();
이 코드는 현재
node
을 cluster
에 추가하려고 시도하였으며, 서로 다른 Discovery
은 서로 다른 실현을 하였으며, 기본 실현은 ZenDiscovery
이다. if (initialStateTimeout.millis() > 0) {
final ThreadPool thread = injector.getInstance(ThreadPool.class);
ClusterState clusterState = clusterService.state();
ClusterStateObserver observer = new ClusterStateObserver(clusterState, clusterService, null, logger, thread.getThreadContext());
if (clusterState.nodes().getMasterNodeId() == null) {
logger.debug("waiting to join the cluster. timeout [{}]", initialStateTimeout);
final CountDownLatch latch = new CountDownLatch(1);
observer.waitForNextChange(new ClusterStateObserver.Listener() {
@Override
public void onNewClusterState(ClusterState state) { latch.countDown(); }
@Override
public void onClusterServiceClose() {
latch.countDown();
}
@Override
public void onTimeout(TimeValue timeout) {
logger.warn("timed out while waiting for initial discovery state - timeout: {}",
initialStateTimeout);
latch.countDown();
}
}, state -> state.nodes().getMasterNodeId() != null, initialStateTimeout);
try {
latch.await();
} catch (InterruptedException e) {
throw new ElasticsearchTimeoutException("Interrupted while waiting for initial discovery state");
}
}
}
cluster
에 가입하려면 먼저 master
노드를 찾아야 하고 master
노드를 찾는 데 시간이 걸립니다. 여기는 master
노드가 나타나거나 시간 초과(기본 30초)가 끝날 때까지 기다립니다.http 사용
if (NetworkModule.HTTP_ENABLED.get(settings)) {
injector.getInstance(HttpServerTransport.class).start();
}
여기에는 기본적으로
http
이 설정되어 있으며 인쇄 로그는 다음과 같습니다.[2018-10-24T19:13:07,544][INFO ][o.e.x.s.t.n.SecurityNetty4HttpServerTransport] [localhost-debug] publish_address {xx.xx.xx.xx:9200}, bound_addresses {xx.xx.xx.xx:9200}
여기까지 현재 노드가 성공적으로 시작되었습니다. 이때
master
노드를 선택하지 않았을 수도 있습니다. cluster
에 가입하지 않았지만 괜찮습니다. 집단 서비스를 제공할 수 없지만 이 노드를 통해 일부 서비스를 제공할 수 있습니다(http
요청 테스트를 보낼 수 있습니다).
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
kafka connect e elasticsearch를 관찰할 수 있습니다.No menu lateral do dashboard tem a opção de connectors onde ele mostra todos os clusters do kafka connect conectados atu...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.