本文主要研究一下Elasticsearch的BootstrapCheck

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;    }}
  • BootstrapCheck接口定义了check方法,该方法返回BootstrapCheckResult,另外还定义了一个default方法alwaysEnforce,默认返回false

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);    }    //......}
  • BootstrapChecks的checks方法返回了一系列BootstrapCheck,其中包括HeapSizeCheck、FileDescriptorCheck、MaxNumberOfThreadsCheck、MaxSizeVirtualMemoryCheck、MaxFileSizeCheck等

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要求max file descriptors不得小于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要求jvm是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对oracle java8开启G1的话要求update是40以后,避免data corruption

小结

  • BootstrapCheck接口定义了check方法,该方法返回BootstrapCheckResult,另外还定义了一个default方法alwaysEnforce,默认返回false
  • BootstrapChecks的checks方法返回了一系列BootstrapCheck,其中包括HeapSizeCheck、FileDescriptorCheck、MaxNumberOfThreadsCheck、MaxSizeVirtualMemoryCheck、MaxFileSizeCheck等
  • FileDescriptorCheck要求max file descriptors不得小于65535;ClientJvmCheck要求jvm是server VM;G1GCCheck对oracle java8开启G1的话要求update是40以后,避免data corruption

doc

  • BootstrapCheck