[FEATURE] Support IO_URING mode in netty

This commit is contained in:
Gravita 2025-02-18 15:14:55 +07:00
parent 41f93b9f8d
commit bbff0eac64
5 changed files with 52 additions and 28 deletions

View file

@ -88,9 +88,12 @@ pack project(':LauncherAPI')
bundle group: 'io.netty', name: 'netty-transport-classes-epoll', version: rootProject['verNetty']
bundle group: 'io.netty', name: 'netty-transport-native-epoll', version: rootProject['verNetty'], classifier: 'linux-x86_64'
bundle group: 'io.netty', name: 'netty-transport-native-epoll', version: rootProject['verNetty'], classifier: 'linux-aarch_64'
bundle group: 'io.netty', name: 'netty-transport-classes-io_uring', version: rootProject['verNetty']
bundle group: 'io.netty', name: 'netty-transport-native-io_uring', version: rootProject['verNetty'], classifier: 'linux-x86_64'
bundle group: 'io.netty', name: 'netty-transport-native-io_uring', version: rootProject['verNetty'], classifier: 'linux-aarch_64'
// Netty
implementation 'org.jboss.marshalling:jboss-marshalling:1.4.11.Final'
implementation 'com.google.protobuf.nano:protobuf-javanano:3.1.0'
bundle 'org.jboss.marshalling:jboss-marshalling:1.4.11.Final'
bundle 'com.google.protobuf.nano:protobuf-javanano:3.1.0'
//
bundle group: 'org.slf4j', name: 'slf4j-api', version: rootProject['verSlf4j']
bundle group: 'com.mysql', name: 'mysql-connector-j', version: rootProject['verMySQLConn']

View file

@ -18,7 +18,7 @@
import java.util.stream.Stream;
public class Main {
private static final List<String> classpathOnly = List.of("proguard", "jline", "progressbar", "kotlin", "epoll");
private static final List<String> classpathOnly = List.of("proguard", "jline", "progressbar", "kotlin");
private static final String LOG4J_PROPERTY = "log4j2.configurationFile";
private static final String DEBUG_PROPERTY = "launchserver.main.debug";
private static final String LIBRARIES_PROPERTY = "launchserver.dir.libraries";

View file

@ -19,6 +19,7 @@
import pro.gravit.launchserver.components.AuthLimiterComponent;
import pro.gravit.launchserver.components.Component;
import pro.gravit.launchserver.components.ProGuardComponent;
import pro.gravit.launchserver.socket.NettyObjectFactory;
import java.util.*;
@ -64,12 +65,7 @@ public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
newConfig.netty.fileServerEnabled = true;
newConfig.netty.binds = new NettyBindAddress[]{new NettyBindAddress("0.0.0.0", 9274)};
newConfig.netty.performance = new NettyPerformanceConfig();
try {
newConfig.netty.performance.usingEpoll = Epoll.isAvailable();
} catch (Throwable e) {
// Epoll class line 51+ catch (Exception) but Error will be thrown by System.load
newConfig.netty.performance.usingEpoll = false;
} // such as on ARM
newConfig.netty.performance.mode = NettyObjectFactory.NettyFactoryMode.AUTO;
newConfig.netty.performance.bossThread = 2;
newConfig.netty.performance.workerThread = 8;
newConfig.netty.performance.schedulerThread = 2;
@ -277,7 +273,7 @@ public static class NettyConfig {
}
public static class NettyPerformanceConfig {
public boolean usingEpoll;
public NettyObjectFactory.NettyFactoryMode mode = NettyObjectFactory.NettyFactoryMode.AUTO;
public int bossThread;
public int workerThread;
public int schedulerThread;

View file

@ -36,14 +36,9 @@ public class LauncherNettyServer implements AutoCloseable {
public LauncherNettyServer(LaunchServer server) {
LaunchServerConfig.NettyConfig config = server.config.netty;
NettyObjectFactory.setUsingEpoll(config.performance.usingEpoll);
NettyObjectFactory.setMode(config.performance.mode);
Logger logger = LogManager.getLogger();
if (config.performance.usingEpoll) {
logger.debug("Netty: Epoll enabled");
}
if (config.performance.usingEpoll && !Epoll.isAvailable()) {
logger.error("Epoll is not available: (netty,perfomance.usingEpoll configured wrongly)", Epoll.unavailabilityCause());
}
logger.info("Netty usage {} transport mode", NettyObjectFactory.getMode());
bossGroup = NettyObjectFactory.newEventLoopGroup(config.performance.bossThread, "LauncherNettyServer.bossGroup");
workerGroup = NettyObjectFactory.newEventLoopGroup(config.performance.workerThread, "LauncherNettyServer.workerGroup");
serverBootstrap = new ServerBootstrap();

View file

@ -2,30 +2,60 @@
import io.netty.channel.ChannelFactory;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.MultiThreadIoEventLoopGroup;
import io.netty.channel.ServerChannel;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollIoHandler;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.nio.NioIoHandler;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.uring.IoUring;
import io.netty.channel.uring.IoUringIoHandler;
import io.netty.channel.uring.IoUringServerSocketChannel;
public class NettyObjectFactory {
private static boolean epoll = false;
private static NettyFactoryMode mode;
public static void setUsingEpoll(boolean value) {
epoll = value;
public static void setMode(NettyFactoryMode mode) {
NettyObjectFactory.mode = mode;
if(mode == NettyFactoryMode.AUTO) {
if(IoUring.isAvailable()) {
NettyObjectFactory.mode = NettyFactoryMode.IO_URING;
return;
}
if(Epoll.isAvailable()) {
NettyObjectFactory.mode = NettyFactoryMode.EPOLL;
return;
}
NettyObjectFactory.mode = NettyFactoryMode.NIO;
}
}
public static NettyFactoryMode getMode() {
return mode;
}
public static EventLoopGroup newEventLoopGroup(int threads, String poolName) {
if (epoll)
return new EpollEventLoopGroup(threads);
else
return new NioEventLoopGroup(threads);
return switch (mode) {
case AUTO -> null;
case NIO -> new MultiThreadIoEventLoopGroup(threads, NioIoHandler.newFactory());
case EPOLL -> new MultiThreadIoEventLoopGroup(threads, EpollIoHandler.newFactory());
case IO_URING -> new MultiThreadIoEventLoopGroup(threads, IoUringIoHandler.newFactory());
};
}
public static ChannelFactory<? extends ServerChannel> getServerSocketChannelFactory() {
if (epoll)
return EpollServerSocketChannel::new;
else
return NioServerSocketChannel::new;
return switch (mode) {
case AUTO -> null;
case NIO -> NioServerSocketChannel::new;
case EPOLL -> EpollServerSocketChannel::new;
case IO_URING -> IoUringServerSocketChannel::new;
};
}
public enum NettyFactoryMode {
AUTO, NIO, EPOLL, IO_URING
}
}