order
This paper mainly studies bootstrap check of elastic search
BootstrapCheck
elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/bootstrap/BootstrapCheck.java
public interface BootstrapCheck { /** * Encapsulate the result of a bootstrap check. */ final class BootstrapCheckResult { private final String message; private static final BootstrapCheckResult SUCCESS = new BootstrapCheckResult(null); public static BootstrapCheckResult success() { return SUCCESS; } public static BootstrapCheckResult failure(final String message) { Objects.requireNonNull(message); return new BootstrapCheckResult(message); } private BootstrapCheckResult(final String message) { this.message = message; } public boolean isSuccess() { return this == SUCCESS; } public boolean isFailure() { return !isSuccess(); } public String getMessage() { assert isFailure(); assert message != null; return message; } } /** * Test if the node fails the check. * * @param context the bootstrap context * @return the result of the bootstrap check */ BootstrapCheckResult check(BootstrapContext context); default boolean alwaysEnforce() { return false; } }
- The bootstrappcheck interface defines the check method, which returns bootstrappcheckresult. In addition, it defines a default method alwaysEnforce, which returns false by default
BootstrapChecks
elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/bootstrap/BootstrapChecks.java
final class BootstrapChecks { private BootstrapChecks() { } static final String ES_ENFORCE_BOOTSTRAP_CHECKS = "es.enforce.bootstrap.checks"; //...... // the list of checks to execute static List<BootstrapCheck> checks() { final List<BootstrapCheck> checks = new ArrayList<>(); checks.add(new HeapSizeCheck()); final FileDescriptorCheck fileDescriptorCheck = Constants.MAC_OS_X ? new OsXFileDescriptorCheck() : new FileDescriptorCheck(); checks.add(fileDescriptorCheck); checks.add(new MlockallCheck()); if (Constants.LINUX) { checks.add(new MaxNumberOfThreadsCheck()); } if (Constants.LINUX || Constants.MAC_OS_X) { checks.add(new MaxSizeVirtualMemoryCheck()); } if (Constants.LINUX || Constants.MAC_OS_X) { checks.add(new MaxFileSizeCheck()); } if (Constants.LINUX) { checks.add(new MaxMapCountCheck()); } checks.add(new ClientJvmCheck()); checks.add(new UseSerialGCCheck()); checks.add(new SystemCallFilterCheck()); checks.add(new OnErrorCheck()); checks.add(new OnOutOfMemoryErrorCheck()); checks.add(new EarlyAccessCheck()); checks.add(new G1GCCheck()); checks.add(new AllPermissionCheck()); checks.add(new DiscoveryConfiguredCheck()); return Collections.unmodifiableList(checks); } //...... }
- The checks method of bootstrappchecks returns a series of bootstrappchecks, including headsizecheck, FileDescriptorCheck, MaxNumberOfThreadsCheck, maxsizevtualmemorycheck, MaxFileSizeCheck, etc
FileDescriptorCheck
static class FileDescriptorCheck implements BootstrapCheck { private final int limit; FileDescriptorCheck() { this(65535); } protected FileDescriptorCheck(final int limit) { if (limit <= 0) { throw new IllegalArgumentException("limit must be positive but was [" + limit + "]"); } this.limit = limit; } public final BootstrapCheckResult check(BootstrapContext context) { final long maxFileDescriptorCount = getMaxFileDescriptorCount(); if (maxFileDescriptorCount != -1 && maxFileDescriptorCount < limit) { final String message = String.format( Locale.ROOT, "max file descriptors [%d] for elasticsearch process is too low, increase to at least [%d]", getMaxFileDescriptorCount(), limit); return BootstrapCheckResult.failure(message); } else { return BootstrapCheckResult.success(); } } // visible for testing long getMaxFileDescriptorCount() { return ProcessProbe.getInstance().getMaxFileDescriptorCount(); } }
- FileDescriptorCheck requires max file descriptors to be no less than 65535
ClientJvmCheck
elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/bootstrap/BootstrapChecks.java
static class ClientJvmCheck implements BootstrapCheck { @Override public BootstrapCheckResult check(BootstrapContext context) { if (getVmName().toLowerCase(Locale.ROOT).contains("client")) { final String message = String.format( Locale.ROOT, "JVM is using the client VM [%s] but should be using a server VM for the best performance", getVmName()); return BootstrapCheckResult.failure(message); } else { return BootstrapCheckResult.success(); } } // visible for testing String getVmName() { return JvmInfo.jvmInfo().getVmName(); } }
- ClientJvmCheck requires that the jvm is a server VM
G1GCCheck
static class G1GCCheck implements BootstrapCheck { @Override public BootstrapCheckResult check(BootstrapContext context) { if ("Oracle Corporation".equals(jvmVendor()) && isJava8() && isG1GCEnabled()) { final String jvmVersion = jvmVersion(); // HotSpot versions on Java 8 match this regular expression; note that this changes with Java 9 after JEP-223 final Pattern pattern = Pattern.compile("(\\d+)\\.(\\d+)-b\\d+"); final Matcher matcher = pattern.matcher(jvmVersion); final boolean matches = matcher.matches(); assert matches : jvmVersion; final int major = Integer.parseInt(matcher.group(1)); final int update = Integer.parseInt(matcher.group(2)); // HotSpot versions for Java 8 have major version 25, the bad versions are all versions prior to update 40 if (major == 25 && update < 40) { final String message = String.format( Locale.ROOT, "JVM version [%s] can cause data corruption when used with G1GC; upgrade to at least Java 8u40", jvmVersion); return BootstrapCheckResult.failure(message); } } return BootstrapCheckResult.success(); } // visible for testing String jvmVendor() { return Constants.JVM_VENDOR; } // visible for testing boolean isG1GCEnabled() { assert "Oracle Corporation".equals(jvmVendor()); return JvmInfo.jvmInfo().useG1GC().equals("true"); } // visible for testing String jvmVersion() { assert "Oracle Corporation".equals(jvmVendor()); return Constants.JVM_VERSION; } // visible for testing boolean isJava8() { assert "Oracle Corporation".equals(jvmVendor()); return JavaVersion.current().equals(JavaVersion.parse("1.8")); } }
- G1GCCheck requires that the data corruption be avoided after the update is 40 when enabling G1 in oracle java8
Summary
- The bootstrappcheck interface defines the check method, which returns bootstrappcheckresult. In addition, it defines a default method alwaysEnforce, which returns false by default
- The checks method of bootstrappchecks returns a series of bootstrappchecks, including headsizecheck, FileDescriptorCheck, MaxNumberOfThreadsCheck, maxsizevtualmemorycheck, MaxFileSizeCheck, etc
- FileDescriptorCheck requires that max file descriptors should not be less than 65535; ClientJvmCheck requires that jvm is server VM; G1GCCheck requires that update is 40 after enabling G1 in oracle java8 to avoid data corruption