Skip to content

Commit

Permalink
Set useOpenSsl in Flags lazily to reduce server startup time (line#2184)
Browse files Browse the repository at this point in the history
Motivation:
Related line#1645
`useOpenSsl` in `Flags` is used only when TLS is enabled. However, it takes a lot to instantiate `OpenSsl` class so it adds up a tremendous time to the server startup time. We should fix to instantiate it only when it needs.

Modification:
- Set `useOpenSsl` in `Flags` lazily
- Check whether the OS is Linux before calling `Epoll.isAvailable()`
- Add `OsType`

Result:
- Reduced server startup time to 80 percent (20% decreased)
  • Loading branch information
mumgmangmange authored and minwoox committed Oct 25, 2019
1 parent d4c4919 commit e72eed3
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 33 deletions.
66 changes: 37 additions & 29 deletions core/src/main/java/com/linecorp/armeria/common/Flags.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import com.linecorp.armeria.client.retry.RetryingRpcClient;
import com.linecorp.armeria.common.util.Exceptions;
import com.linecorp.armeria.common.util.Sampler;
import com.linecorp.armeria.common.util.SystemInfo;
import com.linecorp.armeria.internal.SslContextUtil;
import com.linecorp.armeria.server.RoutingContext;
import com.linecorp.armeria.server.ServerBuilder;
Expand Down Expand Up @@ -117,9 +118,8 @@ public final class Flags {
private static final boolean HAS_WSLENV = System.getenv("WSLENV") != null;
private static final boolean USE_EPOLL = getBoolean("useEpoll", isEpollAvailable(),
value -> isEpollAvailable() || !value);

private static final boolean USE_OPENSSL = getBoolean("useOpenSsl", OpenSsl.isAvailable(),
value -> OpenSsl.isAvailable() || !value);
@Nullable
private static Boolean useOpenSsl;

private static final boolean DUMP_OPENSSL_INFO = getBoolean("dumpOpenSslInfo", false);

Expand Down Expand Up @@ -312,34 +312,15 @@ public final class Flags {
} else if (USE_EPOLL) {
logger.info("Using /dev/epoll");
}

if (!OpenSsl.isAvailable()) {
final Throwable cause = Exceptions.peel(OpenSsl.unavailabilityCause());
logger.info("OpenSSL not available: {}", cause.toString());
} else if (USE_OPENSSL) {
logger.info("Using OpenSSL: {}, 0x{}",
OpenSsl.versionString(),
Long.toHexString(OpenSsl.version() & 0xFFFFFFFFL));

if (dumpOpenSslInfo()) {
final SSLEngine engine = SslContextUtil.createSslContext(
SslContextBuilder::forClient,
false,
unused -> {}).newEngine(ByteBufAllocator.DEFAULT);
logger.info("All available SSL protocols: {}",
ImmutableList.copyOf(engine.getSupportedProtocols()));
logger.info("Default enabled SSL protocols: {}", SslContextUtil.DEFAULT_PROTOCOLS);
ReferenceCountUtil.release(engine);
logger.info("All available SSL ciphers: {}", OpenSsl.availableJavaCipherSuites());
logger.info("Default enabled SSL ciphers: {}", SslContextUtil.DEFAULT_CIPHERS);
}
}
}

private static boolean isEpollAvailable() {
// Netty epoll transport does not work with WSL (Windows Sybsystem for Linux) yet.
// TODO(trustin): Re-enable on WSL if https://github.com/Microsoft/WSL/issues/1982 is resolved.
return Epoll.isAvailable() && !HAS_WSLENV;
if (SystemInfo.isLinux()) {
// Netty epoll transport does not work with WSL (Windows Sybsystem for Linux) yet.
// TODO(trustin): Re-enable on WSL if https://github.com/Microsoft/WSL/issues/1982 is resolved.
return Epoll.isAvailable() && !HAS_WSLENV;
}
return false;
}

/**
Expand Down Expand Up @@ -426,7 +407,34 @@ public static boolean useEpoll() {
* {@code -Dcom.linecorp.armeria.useOpenSsl=false} JVM option to disable it.
*/
public static boolean useOpenSsl() {
return USE_OPENSSL;
if (useOpenSsl != null) {
return useOpenSsl;
}
final boolean useOpenSsl = getBoolean("useOpenSsl", true);
if (!useOpenSsl) {
// OpenSSL explicitly disabled
return Flags.useOpenSsl = false;
}
if (!OpenSsl.isAvailable()) {
final Throwable cause = Exceptions.peel(OpenSsl.unavailabilityCause());
logger.info("OpenSSL not available: {}", cause.toString());
return Flags.useOpenSsl = false;
}
logger.info("Using OpenSSL: {}, 0x{}", OpenSsl.versionString(),
Long.toHexString(OpenSsl.version() & 0xFFFFFFFFL));
if (dumpOpenSslInfo()) {
final SSLEngine engine = SslContextUtil.createSslContext(
SslContextBuilder::forClient,
false,
unused -> {}).newEngine(ByteBufAllocator.DEFAULT);
logger.info("All available SSL protocols: {}",
ImmutableList.copyOf(engine.getSupportedProtocols()));
logger.info("Default enabled SSL protocols: {}", SslContextUtil.DEFAULT_PROTOCOLS);
ReferenceCountUtil.release(engine);
logger.info("All available SSL ciphers: {}", OpenSsl.availableJavaCipherSuites());
logger.info("Default enabled SSL ciphers: {}", SslContextUtil.DEFAULT_CIPHERS);
}
return Flags.useOpenSsl = true;
}

/**
Expand Down
27 changes: 27 additions & 0 deletions core/src/main/java/com/linecorp/armeria/common/util/OsType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2019 LINE Corporation
*
* LINE Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package com.linecorp.armeria.common.util;

/**
* Operating system.
*/
public enum OsType {
WINDOWS,
LINUX,
MAC,
OTHERS
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ public final class SystemInfo {

private static boolean JETTY_ALPN_OPTIONAL_OR_AVAILABLE;

private static final OsType osType;

static {
int javaVersion = -1;
try {
Expand Down Expand Up @@ -109,6 +111,17 @@ public final class SystemInfo {
JETTY_ALPN_OPTIONAL_OR_AVAILABLE = false;
}
}

final String osName = Ascii.toUpperCase(System.getProperty("os.name", ""));
if (osName.startsWith("WINDOWS")) {
osType = OsType.WINDOWS;
} else if (osName.startsWith("LINUX")) {
osType = OsType.LINUX;
} else if (osName.startsWith("MAC")) {
osType = OsType.MAC;
} else {
osType = OsType.OTHERS;
}
}

/**
Expand Down Expand Up @@ -154,8 +167,18 @@ public static long currentTimeMicros() {
return JavaVersionSpecific.get().currentTimeMicros();
}

private static boolean isLinux() {
return Ascii.toLowerCase(System.getProperty("os.name", "")).startsWith("linux");
/**
* Returns the operating system for the currently running process.
*/
public static OsType osType() {
return osType;
}

/**
* Returns {@code true} if the operating system is Linux.
*/
public static boolean isLinux() {
return osType == OsType.LINUX;
}

private SystemInfo() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.handler.ssl.OpenSsl;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.util.DomainNameMapping;
Expand Down Expand Up @@ -1576,7 +1575,7 @@ public Server build() {
ports = ImmutableList.of(new ServerPort(0, HTTP));
}
} else {
if ((!OpenSsl.isAvailable() || !Flags.useOpenSsl()) && !SystemInfo.jettyAlpnOptionalOrAvailable()) {
if (!Flags.useOpenSsl() && !SystemInfo.jettyAlpnOptionalOrAvailable()) {
throw new IllegalStateException(
"TLS configured but this is Java 8 and neither OpenSSL nor Jetty ALPN could be " +
"detected. To use TLS with Armeria, you must either use Java 9+, enable OpenSSL, " +
Expand Down

0 comments on commit e72eed3

Please sign in to comment.