本文主要研究一下Elasticsearch的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; } }
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); } //...... }
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(); } }
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(); } }
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")); } }