This commit is contained in:
道君 2024-06-30 04:45:26 +02:00 committed by GitHub
commit 49a36c8a6e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 111 additions and 17 deletions

View File

@ -122,6 +122,8 @@ public interface Constants {
String NETTY_EPOLL_ENABLE_KEY = "netty.epoll.enable"; String NETTY_EPOLL_ENABLE_KEY = "netty.epoll.enable";
String NETTY_IO_URING_ENABLE_KEY = "netty.io_uring.enable";
String BIND_IP_KEY = "bind.ip"; String BIND_IP_KEY = "bind.ip";
String BIND_PORT_KEY = "bind.port"; String BIND_PORT_KEY = "bind.port";

View File

@ -33,6 +33,7 @@
<properties> <properties>
<skip_maven_deploy>false</skip_maven_deploy> <skip_maven_deploy>false</skip_maven_deploy>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<netty-iouring.version>0.0.21.Final</netty-iouring.version>
</properties> </properties>
<dependencies> <dependencies>
@ -70,5 +71,24 @@
<classifier>linux-aarch_64</classifier> <classifier>linux-aarch_64</classifier>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<!-- io_uring deps -->
<dependency>
<groupId>io.netty.incubator</groupId>
<artifactId>netty-incubator-transport-classes-io_uring</artifactId>
<version>${netty-iouring.version}</version>
</dependency>
<dependency>
<groupId>io.netty.incubator</groupId>
<artifactId>netty-incubator-transport-native-io_uring</artifactId>
<version>${netty-iouring.version}</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>io.netty.incubator</groupId>
<artifactId>netty-incubator-transport-native-io_uring</artifactId>
<version>${netty-iouring.version}</version>
<classifier>linux-aarch_64</classifier>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -16,11 +16,6 @@
*/ */
package org.apache.dubbo.remoting.transport.netty4; package org.apache.dubbo.remoting.transport.netty4;
import org.apache.dubbo.common.resource.GlobalResourceInitializer;
import org.apache.dubbo.remoting.Constants;
import java.util.concurrent.ThreadFactory;
import io.netty.channel.EventLoopGroup; import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.Epoll; import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.epoll.EpollEventLoopGroup;
@ -31,34 +26,59 @@ import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.incubator.channel.uring.IOUring;
import io.netty.incubator.channel.uring.IOUringEventLoopGroup;
import io.netty.incubator.channel.uring.IOUringServerSocketChannel;
import io.netty.incubator.channel.uring.IOUringSocketChannel;
import io.netty.util.concurrent.DefaultThreadFactory; import io.netty.util.concurrent.DefaultThreadFactory;
import org.apache.dubbo.common.resource.GlobalResourceInitializer;
import org.apache.dubbo.remoting.Constants;
import java.util.concurrent.ThreadFactory;
import static org.apache.dubbo.common.constants.CommonConstants.OS_LINUX_PREFIX; import static org.apache.dubbo.common.constants.CommonConstants.OS_LINUX_PREFIX;
import static org.apache.dubbo.common.constants.CommonConstants.OS_NAME_KEY; import static org.apache.dubbo.common.constants.CommonConstants.OS_NAME_KEY;
import static org.apache.dubbo.remoting.Constants.NETTY_EPOLL_ENABLE_KEY; import static org.apache.dubbo.remoting.Constants.NETTY_EPOLL_ENABLE_KEY;
import static org.apache.dubbo.remoting.Constants.NETTY_IO_URING_ENABLE_KEY;
public class NettyEventLoopFactory { public class NettyEventLoopFactory {
/** /**
* netty client bootstrap * netty client bootstrap
*/ */
public static final GlobalResourceInitializer<EventLoopGroup> NIO_EVENT_LOOP_GROUP = public static final GlobalResourceInitializer<EventLoopGroup> NIO_EVENT_LOOP_GROUP =
new GlobalResourceInitializer<>( new GlobalResourceInitializer<>(
() -> eventLoopGroup(Constants.DEFAULT_IO_THREADS, "NettyClientWorker"), () -> eventLoopGroup(Constants.DEFAULT_IO_THREADS, "NettyClientWorker"),
eventLoopGroup -> eventLoopGroup.shutdownGracefully()); eventLoopGroup -> eventLoopGroup.shutdownGracefully());
public static EventLoopGroup eventLoopGroup(int threads, String threadFactoryName) { public static EventLoopGroup eventLoopGroup(int threads, String threadFactoryName) {
ThreadFactory threadFactory = new DefaultThreadFactory(threadFactoryName, true); ThreadFactory threadFactory = new DefaultThreadFactory(threadFactoryName, true);
return shouldEpoll() if (shouldIOUring()) {
? new EpollEventLoopGroup(threads, threadFactory) return new EpollEventLoopGroup(threads, threadFactory);
: new NioEventLoopGroup(threads, threadFactory); } else if (shouldIOUring()) {
return new IOUringEventLoopGroup(threads, threadFactory);
} else {
return new NioEventLoopGroup(threads, threadFactory);
}
} }
public static Class<? extends SocketChannel> socketChannelClass() { public static Class<? extends SocketChannel> socketChannelClass() {
return shouldEpoll() ? EpollSocketChannel.class : NioSocketChannel.class; if (shouldEpoll()) {
return EpollSocketChannel.class;
} else if (shouldIOUring()) {
return IOUringSocketChannel.class;
} else {
return NioSocketChannel.class;
}
} }
public static Class<? extends ServerSocketChannel> serverSocketChannelClass() { public static Class<? extends ServerSocketChannel> serverSocketChannelClass() {
return shouldEpoll() ? EpollServerSocketChannel.class : NioServerSocketChannel.class; if (shouldEpoll()) {
return EpollServerSocketChannel.class;
} else if (shouldIOUring()) {
return IOUringServerSocketChannel.class;
} else {
return NioServerSocketChannel.class;
}
} }
private static boolean shouldEpoll() { private static boolean shouldEpoll() {
@ -69,4 +89,13 @@ public class NettyEventLoopFactory {
return false; return false;
} }
private static boolean shouldIOUring() {
if (Boolean.parseBoolean(System.getProperty(NETTY_IO_URING_ENABLE_KEY, "false"))) {
String osName = System.getProperty(OS_NAME_KEY);
return osName.toLowerCase().contains(OS_LINUX_PREFIX) && IOUring.isAvailable();
}
return false;
}
} }

View File

@ -26,6 +26,10 @@ import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.incubator.channel.uring.IOUring;
import io.netty.incubator.channel.uring.IOUringEventLoopGroup;
import io.netty.incubator.channel.uring.IOUringServerSocketChannel;
import io.netty.incubator.channel.uring.IOUringSocketChannel;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
@ -34,6 +38,7 @@ import org.junit.jupiter.api.Test;
import static org.apache.dubbo.common.constants.CommonConstants.OS_LINUX_PREFIX; import static org.apache.dubbo.common.constants.CommonConstants.OS_LINUX_PREFIX;
import static org.apache.dubbo.common.constants.CommonConstants.OS_NAME_KEY; import static org.apache.dubbo.common.constants.CommonConstants.OS_NAME_KEY;
import static org.apache.dubbo.remoting.Constants.NETTY_EPOLL_ENABLE_KEY; import static org.apache.dubbo.remoting.Constants.NETTY_EPOLL_ENABLE_KEY;
import static org.apache.dubbo.remoting.Constants.NETTY_IO_URING_ENABLE_KEY;
/** /**
* {@link NettyEventLoopFactory} * {@link NettyEventLoopFactory}
@ -48,13 +53,15 @@ class NettyEventLoopFactoryTest {
@AfterEach @AfterEach
public void reset() { public void reset() {
System.clearProperty(NETTY_EPOLL_ENABLE_KEY); System.clearProperty(NETTY_EPOLL_ENABLE_KEY);
System.clearProperty(NETTY_IO_URING_ENABLE_KEY);
} }
@Test @Test
void eventLoopGroup() { void eventLoopGroup() {
if (isEpoll()) { if (isEpoll()) {
EventLoopGroup eventLoopGroup = NettyEventLoopFactory.eventLoopGroup(1, "test"); try (EventLoopGroup eventLoopGroup = NettyEventLoopFactory.eventLoopGroup(1, "test")) {
Assertions.assertTrue(eventLoopGroup instanceof EpollEventLoopGroup); Assertions.assertTrue(eventLoopGroup instanceof EpollEventLoopGroup);
}
Class<? extends SocketChannel> socketChannelClass = NettyEventLoopFactory.socketChannelClass(); Class<? extends SocketChannel> socketChannelClass = NettyEventLoopFactory.socketChannelClass();
Assertions.assertEquals(socketChannelClass, EpollSocketChannel.class); Assertions.assertEquals(socketChannelClass, EpollSocketChannel.class);
@ -64,8 +71,9 @@ class NettyEventLoopFactoryTest {
Assertions.assertEquals(serverSocketChannelClass, EpollServerSocketChannel.class); Assertions.assertEquals(serverSocketChannelClass, EpollServerSocketChannel.class);
} else { } else {
EventLoopGroup eventLoopGroup = NettyEventLoopFactory.eventLoopGroup(1, "test"); try (EventLoopGroup eventLoopGroup = NettyEventLoopFactory.eventLoopGroup(1, "test")) {
Assertions.assertTrue(eventLoopGroup instanceof NioEventLoopGroup); Assertions.assertTrue(eventLoopGroup instanceof NioEventLoopGroup);
}
Class<? extends SocketChannel> socketChannelClass = NettyEventLoopFactory.socketChannelClass(); Class<? extends SocketChannel> socketChannelClass = NettyEventLoopFactory.socketChannelClass();
Assertions.assertEquals(socketChannelClass, NioSocketChannel.class); Assertions.assertEquals(socketChannelClass, NioSocketChannel.class);
@ -76,6 +84,41 @@ class NettyEventLoopFactoryTest {
} }
} }
@Test
void testIOUringEventLoop() {
System.setProperty(NETTY_EPOLL_ENABLE_KEY, "false");
System.setProperty(NETTY_IO_URING_ENABLE_KEY, "true");
if (isIOUring()) {
try (EventLoopGroup eventLoopGroup = NettyEventLoopFactory.eventLoopGroup(1, "test")) {
Assertions.assertTrue(eventLoopGroup instanceof IOUringEventLoopGroup);
}
Class<?> socketChannelClass = NettyEventLoopFactory.socketChannelClass();
Assertions.assertEquals(socketChannelClass, IOUringSocketChannel.class);
Class<?> serverSocketChannelClass = NettyEventLoopFactory.serverSocketChannelClass();
Assertions.assertEquals(serverSocketChannelClass, IOUringServerSocketChannel.class);
} else {
try (EventLoopGroup eventLoopGroup = NettyEventLoopFactory.eventLoopGroup(1, "test")) {
Assertions.assertTrue(eventLoopGroup instanceof NioEventLoopGroup);
}
Class<? extends SocketChannel> socketChannelClass = NettyEventLoopFactory.socketChannelClass();
Assertions.assertEquals(socketChannelClass, NioSocketChannel.class);
Class<? extends ServerSocketChannel> serverSocketChannelClass =
NettyEventLoopFactory.serverSocketChannelClass();
Assertions.assertEquals(serverSocketChannelClass, NioServerSocketChannel.class);
}
}
private boolean isIOUring() {
String osName = System.getProperty(OS_NAME_KEY);
return osName.toLowerCase().contains(OS_LINUX_PREFIX) && IOUring.isAvailable();
}
private boolean isEpoll() { private boolean isEpoll() {
String osName = System.getProperty(OS_NAME_KEY); String osName = System.getProperty(OS_NAME_KEY);
return osName.toLowerCase().contains(OS_LINUX_PREFIX) && Epoll.isAvailable(); return osName.toLowerCase().contains(OS_LINUX_PREFIX) && Epoll.isAvailable();