diff --git a/build.gradle b/build.gradle index 7a1b37c86..6d4f7e8d7 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ allprojects { junitVersion = '5.7.0' slf4jVersion = '1.7.30' log4jVersion = '2.13.3' - nettyVersion = '4.1.52.Final' + nettyVersion = '4.1.54.Final' guavaVersion = '25.1-jre' checkerFrameworkVersion = '3.6.1' configurateVersion = '3.7.1' diff --git a/proxy/build.gradle b/proxy/build.gradle index ff2e1fe0a..37278fc80 100644 --- a/proxy/build.gradle +++ b/proxy/build.gradle @@ -52,6 +52,7 @@ dependencies { implementation "io.netty:netty-transport-native-epoll:${nettyVersion}" implementation "io.netty:netty-transport-native-epoll:${nettyVersion}:linux-x86_64" implementation "io.netty:netty-transport-native-epoll:${nettyVersion}:linux-aarch64" + implementation "io.netty.incubator:netty-incubator-transport-native-io_uring:0.0.1.Final:linux-x86_64" implementation "io.netty:netty-resolver-dns:${nettyVersion}" implementation "org.apache.logging.log4j:log4j-api:${log4jVersion}" diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java b/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java index c5408fc60..0683e16d4 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java @@ -16,6 +16,7 @@ import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.WriteBufferWaterMark; import io.netty.channel.epoll.EpollChannelOption; +import io.netty.incubator.channel.uring.IOUringChannelOption; import io.netty.util.concurrent.GlobalEventExecutor; import java.net.InetSocketAddress; import java.util.HashMap; @@ -23,6 +24,7 @@ import java.util.Map; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.asynchttpclient.AsyncHttpClient; +import org.asynchttpclient.DefaultAsyncHttpClientConfig; import org.asynchttpclient.RequestBuilder; import org.asynchttpclient.filter.FilterContext; import org.asynchttpclient.filter.FilterContext.FilterContextBuilder; @@ -64,20 +66,23 @@ public final class ConnectionManager { this.backendChannelInitializer = new BackendChannelInitializerHolder( new BackendChannelInitializer(this.server)); this.resolver = new SeparatePoolInetNameResolver(GlobalEventExecutor.INSTANCE); - this.httpClient = asyncHttpClient(config() - .setEventLoopGroup(this.workerGroup) + + DefaultAsyncHttpClientConfig.Builder httpClientBuilder = config() .setUserAgent(server.getVersion().getName() + "/" + server.getVersion().getVersion()) .addRequestFilter(new RequestFilter() { @Override public FilterContext filter(FilterContext ctx) { return new FilterContextBuilder<>(ctx) - .request(new RequestBuilder(ctx.getRequest()) + .request(ctx.getRequest().toBuilder() .setNameResolver(resolver) .build()) .build(); } - }) - .build()); + }); + if (this.transportType != TransportType.IO_URING) { + httpClientBuilder = httpClientBuilder.setEventLoopGroup(this.workerGroup); + } + this.httpClient = asyncHttpClient(httpClientBuilder.build()); } public void logChannelInformation() { @@ -100,8 +105,12 @@ public final class ConnectionManager { .childOption(ChannelOption.IP_TOS, 0x18) .localAddress(address); - if (transportType == TransportType.EPOLL && server.getConfiguration().useTcpFastOpen()) { - bootstrap.option(EpollChannelOption.TCP_FASTOPEN, 3); + if (server.getConfiguration().useTcpFastOpen()) { + if (transportType == TransportType.EPOLL) { + bootstrap.option(EpollChannelOption.TCP_FASTOPEN, 3); + } else if (transportType == TransportType.IO_URING) { + bootstrap.option(IOUringChannelOption.TCP_FASTOPEN, 3); + } } bootstrap.bind() @@ -156,8 +165,12 @@ public final class ConnectionManager { this.server.getConfiguration().getConnectTimeout()) .group(group == null ? this.workerGroup : group) .resolver(this.resolver.asGroup()); - if (transportType == TransportType.EPOLL && server.getConfiguration().useTcpFastOpen()) { - bootstrap.option(EpollChannelOption.TCP_FASTOPEN_CONNECT, true); + if (server.getConfiguration().useTcpFastOpen()) { + if (transportType == TransportType.EPOLL) { + bootstrap.option(EpollChannelOption.TCP_FASTOPEN_CONNECT, true); + } else if (transportType == TransportType.IO_URING) { + bootstrap.option(IOUringChannelOption.TCP_FASTOPEN_CONNECT, true); + } } return bootstrap; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/TransportType.java b/proxy/src/main/java/com/velocitypowered/proxy/network/TransportType.java index d241267b9..ef16c9168 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/TransportType.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/TransportType.java @@ -15,6 +15,11 @@ import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.incubator.channel.uring.IOUring; +import io.netty.incubator.channel.uring.IOUringDatagramChannel; +import io.netty.incubator.channel.uring.IOUringEventLoopGroup; +import io.netty.incubator.channel.uring.IOUringServerSocketChannel; +import io.netty.incubator.channel.uring.IOUringSocketChannel; import java.util.concurrent.ThreadFactory; import java.util.function.BiFunction; @@ -26,7 +31,11 @@ enum TransportType { EPOLL("epoll", EpollServerSocketChannel::new, EpollSocketChannel::new, EpollDatagramChannel::new, - (name, type) -> new EpollEventLoopGroup(0, createThreadFactory(name, type))); + (name, type) -> new EpollEventLoopGroup(0, createThreadFactory(name, type))), + IO_URING("io_uring", IOUringServerSocketChannel::new, + IOUringSocketChannel::new, + IOUringDatagramChannel::new, + (name, type) -> new IOUringEventLoopGroup(0, createThreadFactory(name, type))); final String name; final ChannelFactory serverSocketChannelFactory; @@ -64,7 +73,9 @@ enum TransportType { return NIO; } - if (Epoll.isAvailable()) { + if (IOUring.isAvailable()) { + return IO_URING; + } else if (Epoll.isAvailable()) { return EPOLL; } else { return NIO;