Skip to content

Commit 38f4829

Browse files
AntonRoskvistjbertram
authored andcommitted
ARTEMIS-3163 Support for Netty IO_URING transport
1 parent 4f1b69a commit 38f4829

File tree

10 files changed

+118
-5
lines changed

10 files changed

+118
-5
lines changed

artemis-core-client/pom.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,15 @@
8989
<groupId>io.netty</groupId>
9090
<artifactId>netty-transport-classes-kqueue</artifactId>
9191
</dependency>
92+
<dependency>
93+
<groupId>io.netty</groupId>
94+
<artifactId>netty-transport-native-io_uring</artifactId>
95+
<classifier>${netty-transport-native-io_uring-classifier}</classifier>
96+
</dependency>
97+
<dependency>
98+
<groupId>io.netty</groupId>
99+
<artifactId>netty-transport-classes-io_uring</artifactId>
100+
</dependency>
92101
<dependency>
93102
<groupId>io.netty</groupId>
94103
<artifactId>netty-codec-http</artifactId>

artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/ActiveMQClientLogger.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,4 +349,10 @@ public interface ActiveMQClientLogger {
349349

350350
@LogMessage(id = 214036, value = "Connection closure to {} has been detected: {} [code={}]", level = LogMessage.Level.INFO)
351351
void connectionClosureDetected(String remoteAddress, String message, ActiveMQExceptionType type);
352+
353+
@LogMessage(id = 214037, value = "Unable to check IoUring availability ", level = LogMessage.Level.WARN)
354+
void unableToCheckIoUringAvailability(Throwable e);
355+
356+
@LogMessage(id = 214038, value = "IoUring is not available, please add to the classpath or configure useIoUring=false to remove this warning", level = LogMessage.Level.WARN)
357+
void unableToCheckIoUringAvailabilitynoClass();
352358
}

artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/CheckDependencies.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import io.netty.channel.epoll.Epoll;
2121
import io.netty.channel.kqueue.KQueue;
22+
import io.netty.channel.uring.IoUring;
2223
import org.apache.activemq.artemis.core.client.ActiveMQClientLogger;
2324
import org.apache.activemq.artemis.utils.Env;
2425

@@ -51,4 +52,17 @@ public static final boolean isKQueueAvailable() {
5152
return false;
5253
}
5354
}
55+
56+
public static final boolean isIoUringAvailable() {
57+
try {
58+
return Env.isLinuxOs() && IoUring.isAvailable();
59+
} catch (NoClassDefFoundError noClassDefFoundError) {
60+
ActiveMQClientLogger.LOGGER.unableToCheckIoUringAvailabilitynoClass();
61+
return false;
62+
} catch (Throwable e) {
63+
ActiveMQClientLogger.LOGGER.unableToCheckIoUringAvailability(e);
64+
return false;
65+
}
66+
}
67+
5468
}

artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@
7373
import io.netty.channel.kqueue.KQueueSocketChannel;
7474
import io.netty.channel.nio.NioIoHandler;
7575
import io.netty.channel.socket.nio.NioSocketChannel;
76+
import io.netty.channel.uring.IoUringIoHandler;
77+
import io.netty.channel.uring.IoUringSocketChannel;
7678
import io.netty.handler.codec.base64.Base64;
7779
import io.netty.handler.codec.http.DefaultFullHttpRequest;
7880
import io.netty.handler.codec.http.DefaultHttpRequest;
@@ -137,6 +139,7 @@ public class NettyConnector extends AbstractConnector {
137139
public static String NIO_CONNECTOR_TYPE = "NIO";
138140
public static String EPOLL_CONNECTOR_TYPE = "EPOLL";
139141
public static String KQUEUE_CONNECTOR_TYPE = "KQUEUE";
142+
public static String IOURING_CONNECTOR_TYPE = "IO_URING";
140143

141144
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
142145

@@ -295,6 +298,8 @@ public class NettyConnector extends AbstractConnector {
295298

296299
private boolean useKQueue;
297300

301+
private boolean useIoUring;
302+
298303
private int remotingThreads;
299304

300305
private boolean useGlobalWorkerPool;
@@ -404,6 +409,7 @@ public NettyConnector(final Map<String, Object> configuration,
404409

405410
useEpoll = ConfigurationHelper.getBooleanProperty(TransportConstants.USE_EPOLL_PROP_NAME, TransportConstants.DEFAULT_USE_EPOLL, configuration);
406411
useKQueue = ConfigurationHelper.getBooleanProperty(TransportConstants.USE_KQUEUE_PROP_NAME, TransportConstants.DEFAULT_USE_KQUEUE, configuration);
412+
useIoUring = ConfigurationHelper.getBooleanProperty(TransportConstants.USE_IOURING_PROP_NAME, TransportConstants.DEFAULT_USE_IOURING, configuration);
407413

408414
useServlet = ConfigurationHelper.getBooleanProperty(TransportConstants.USE_SERVLET_PROP_NAME, TransportConstants.DEFAULT_USE_SERVLET, configuration);
409415
host = ConfigurationHelper.getStringProperty(TransportConstants.HOST_PROP_NAME, TransportConstants.DEFAULT_HOST, configuration);
@@ -528,14 +534,30 @@ public synchronized void start() {
528534
return;
529535
}
530536

531-
if (remotingThreads == -1) {
537+
boolean defaultRemotingThreads = remotingThreads == -1;
538+
539+
if (defaultRemotingThreads) {
532540
// Default to number of cores * 3
533541
remotingThreads = Runtime.getRuntime().availableProcessors() * 3;
534542
}
535543

536544
String connectorType;
537545

538-
if (useEpoll && CheckDependencies.isEpollAvailable()) {
546+
if (useIoUring && CheckDependencies.isIoUringAvailable()) {
547+
//IO_URING should default to 1 remotingThread unless specified in config
548+
remotingThreads = defaultRemotingThreads ? 1 : remotingThreads;
549+
550+
if (useGlobalWorkerPool) {
551+
group = SharedEventLoopGroup.getInstance((threadFactory -> new MultiThreadIoEventLoopGroup(remotingThreads, threadFactory, IoUringIoHandler.newFactory())));
552+
} else {
553+
group = new MultiThreadIoEventLoopGroup(remotingThreads, IoUringIoHandler.newFactory());
554+
}
555+
556+
connectorType = IOURING_CONNECTOR_TYPE;
557+
channelClazz = IoUringSocketChannel.class;
558+
559+
logger.debug("Connector {} using native io_uring", this);
560+
} else if (useEpoll && CheckDependencies.isEpollAvailable()) {
539561
if (useGlobalWorkerPool) {
540562
group = SharedEventLoopGroup.getInstance((threadFactory -> new MultiThreadIoEventLoopGroup(remotingThreads, threadFactory, EpollIoHandler.newFactory())));
541563
} else {

artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/TransportConstants.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ public class TransportConstants {
7070

7171
public static final String USE_KQUEUE_PROP_NAME = "useKQueue";
7272

73+
public static final String USE_IOURING_PROP_NAME = "useIoUring";
74+
7375
/**
7476
* @deprecated Use USE_GLOBAL_WORKER_POOL_PROP_NAME
7577
*/
@@ -218,6 +220,8 @@ public class TransportConstants {
218220

219221
public static final boolean DEFAULT_USE_KQUEUE = true;
220222

223+
public static final boolean DEFAULT_USE_IOURING = false;
224+
221225
public static final boolean DEFAULT_USE_INVM = false;
222226

223227
public static final boolean DEFAULT_USE_SERVLET = false;
@@ -426,6 +430,7 @@ private static int parseDefaultVariable(String variableName, int defaultValue) {
426430
allowableAcceptorKeys.add(TransportConstants.USE_NIO_PROP_NAME);
427431
allowableAcceptorKeys.add(TransportConstants.USE_EPOLL_PROP_NAME);
428432
allowableAcceptorKeys.add(TransportConstants.USE_KQUEUE_PROP_NAME);
433+
allowableAcceptorKeys.add(TransportConstants.USE_IOURING_PROP_NAME);
429434
allowableAcceptorKeys.add(TransportConstants.USE_INVM_PROP_NAME);
430435
//noinspection deprecation
431436
allowableAcceptorKeys.add(TransportConstants.PROTOCOL_PROP_NAME);
@@ -502,6 +507,7 @@ private static int parseDefaultVariable(String variableName, int defaultValue) {
502507
allowableConnectorKeys.add(TransportConstants.USE_NIO_GLOBAL_WORKER_POOL_PROP_NAME);
503508
allowableConnectorKeys.add(TransportConstants.USE_EPOLL_PROP_NAME);
504509
allowableConnectorKeys.add(TransportConstants.USE_KQUEUE_PROP_NAME);
510+
allowableConnectorKeys.add(TransportConstants.USE_IOURING_PROP_NAME);
505511
allowableConnectorKeys.add(TransportConstants.USE_GLOBAL_WORKER_POOL_PROP_NAME);
506512
allowableConnectorKeys.add(TransportConstants.HOST_PROP_NAME);
507513
allowableConnectorKeys.add(TransportConstants.PORT_PROP_NAME);

artemis-features/src/main/resources/features.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
<bundle>mvn:io.netty/netty-transport-native-epoll/${netty.version}</bundle>
4646
<bundle>mvn:io.netty/netty-transport-classes-kqueue/${netty.version}</bundle>
4747
<bundle>mvn:io.netty/netty-transport-native-kqueue/${netty.version}</bundle>
48+
<bundle>mvn:io.netty/netty-transport-classes-io_uring/${netty.version}</bundle>
49+
<bundle>mvn:io.netty/netty-transport-native-io_uring/${netty.version}</bundle>
4850
<bundle>mvn:io.netty/netty-transport-native-unix-common/${netty.version}</bundle>
4951
</feature>
5052

artemis-pom/pom.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,19 @@
480480
<classifier>${netty-transport-native-kqueue-classifier}</classifier>
481481
<!-- License: Apache 2.0 -->
482482
</dependency>
483+
<dependency>
484+
<groupId>io.netty</groupId>
485+
<artifactId>netty-transport-classes-io_uring</artifactId>
486+
<version>${netty.version}</version>
487+
<!-- License: Apache 2.0 -->
488+
</dependency>
489+
<dependency>
490+
<groupId>io.netty</groupId>
491+
<artifactId>netty-transport-native-io_uring</artifactId>
492+
<version>${netty.version}</version>
493+
<classifier>${netty-transport-native-io_uring-classifier}</classifier>
494+
<!-- License: Apache 2.0 -->
495+
</dependency>
483496
<dependency>
484497
<groupId>io.netty</groupId>
485498
<artifactId>netty-tcnative-boringssl-static</artifactId>

artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
import io.netty.channel.local.LocalServerChannel;
6464
import io.netty.channel.nio.NioIoHandler;
6565
import io.netty.channel.socket.nio.NioServerSocketChannel;
66+
import io.netty.channel.uring.IoUringIoHandler;
67+
import io.netty.channel.uring.IoUringServerSocketChannel;
6668
import io.netty.handler.codec.haproxy.HAProxyMessageDecoder;
6769
import io.netty.handler.ssl.SslContext;
6870
import io.netty.handler.ssl.SslHandler;
@@ -118,6 +120,7 @@ public class NettyAcceptor extends AbstractAcceptor {
118120
public static final String NIO_ACCEPTOR_TYPE = "NIO";
119121
public static final String EPOLL_ACCEPTOR_TYPE = "EPOLL";
120122
public static final String KQUEUE_ACCEPTOR_TYPE = "KQUEUE";
123+
public static final String IOURING_ACCEPTOR_TYPE = "IO_URING";
121124

122125
static {
123126
// Disable default Netty leak detection if the Netty leak detection level system properties are not in use
@@ -156,6 +159,8 @@ public class NettyAcceptor extends AbstractAcceptor {
156159

157160
private final boolean useKQueue;
158161

162+
private final boolean useIoUring;
163+
159164
private final ProtocolHandler protocolHandler;
160165

161166
private final String host;
@@ -300,6 +305,7 @@ public NettyAcceptor(final String name,
300305

301306
useEpoll = ConfigurationHelper.getBooleanProperty(TransportConstants.USE_EPOLL_PROP_NAME, TransportConstants.DEFAULT_USE_EPOLL, configuration);
302307
useKQueue = ConfigurationHelper.getBooleanProperty(TransportConstants.USE_KQUEUE_PROP_NAME, TransportConstants.DEFAULT_USE_KQUEUE, configuration);
308+
useIoUring = ConfigurationHelper.getBooleanProperty(TransportConstants.USE_IOURING_PROP_NAME, TransportConstants.DEFAULT_USE_IOURING, configuration);
303309

304310
backlog = ConfigurationHelper.getIntProperty(TransportConstants.BACKLOG_PROP_NAME, -1, configuration);
305311
useInvm = ConfigurationHelper.getBooleanProperty(TransportConstants.USE_INVM_PROP_NAME, TransportConstants.DEFAULT_USE_INVM, configuration);
@@ -449,7 +455,23 @@ public synchronized void start() throws Exception {
449455
eventLoopGroup = new DefaultEventLoopGroup();
450456
} else {
451457
ThreadFactory threadFactory = SecurityManagerShim.doPrivileged((PrivilegedAction<ActiveMQThreadFactory>) () -> new ActiveMQThreadFactory(threadFactoryGroupName, true, ClientSessionFactoryImpl.class.getClassLoader()));
452-
if (useEpoll && CheckDependencies.isEpollAvailable()) {
458+
459+
boolean defaultRemotingThreads = remotingThreads == -1;
460+
461+
if (defaultRemotingThreads) {
462+
// Default to number of cores * 3
463+
remotingThreads = Runtime.getRuntime().availableProcessors() * 3;
464+
}
465+
466+
if (useIoUring && CheckDependencies.isIoUringAvailable()) {
467+
//IO_URING should default to 1 remotingThread unless specified in config
468+
remotingThreads = defaultRemotingThreads ? 1 : remotingThreads;
469+
470+
channelClazz = IoUringServerSocketChannel.class;
471+
eventLoopGroup = new MultiThreadIoEventLoopGroup(remotingThreads, threadFactory, IoUringIoHandler.newFactory());
472+
acceptorType = IOURING_ACCEPTOR_TYPE;
473+
logger.debug("Acceptor using native io_uring");
474+
} else if (useEpoll && CheckDependencies.isEpollAvailable()) {
453475
channelClazz = EpollServerSocketChannel.class;
454476
eventLoopGroup = new MultiThreadIoEventLoopGroup(remotingThreads, threadFactory, EpollIoHandler.newFactory());
455477
acceptorType = EPOLL_ACCEPTOR_TYPE;

docs/user-manual/configuring-transports.adoc

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ These Native transports add features specific to a particular platform, generate
244244

245245
Both Clients and Server can benefit from this.
246246

247-
Current Supported Platforms.
247+
Currently supported platforms:
248248

249249
* Linux running 64bit JVM
250250
* MacOS running 64bit JVM
@@ -255,7 +255,7 @@ If running on an unsupported platform or if there are any issues loading native
255255

256256
==== Linux Native Transport
257257

258-
On supported Linux platforms Epoll is used, @see https://en.wikipedia.org/wiki/Epoll.
258+
On supported Linux platforms Epoll can be used, @see https://en.wikipedia.org/wiki/Epoll.
259259

260260
The following properties are specific to this native transport:
261261

@@ -264,6 +264,24 @@ enables the use of epoll if a supported linux platform is running a 64bit JVM is
264264
Setting this to `false` will force the use of Java NIO instead of epoll.
265265
Default is `true`
266266

267+
Additionally, IO_URING can be used, @see https://en.wikipedia.org/wiki/Io_uring.
268+
269+
The following properties are specific to this native transport:
270+
271+
useIoUring::
272+
enables the use of IO_URING if a supported linux platform running a 64bit JVM is detected.
273+
Setting this to `false` will attempt the use of `epoll`, then finally falling back to using Java NIO.
274+
Default is `false`
275+
276+
[WARNING]
277+
====
278+
[#io_uring-warning]
279+
IO_URING support is a recent addition to the broker and should be considered `experimental` at this stage.
280+
Using it _could_ introduce unwanted side effects. As such, thorough testing and verification are advised before use in any production or otherwise critical environment.
281+
282+
Netty has provided a https://github.com/netty/netty/tree/4.2/transport-native-io_uring#faq[FAQ] that may be helpful.
283+
====
284+
267285
==== MacOS Native Transport
268286

269287
On supported MacOS platforms KQueue is used, @see https://en.wikipedia.org/wiki/Kqueue.

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@
277277

278278
<netty-transport-native-epoll-classifier>linux-x86_64</netty-transport-native-epoll-classifier>
279279
<netty-transport-native-kqueue-classifier>osx-x86_64</netty-transport-native-kqueue-classifier>
280+
<netty-transport-native-io_uring-classifier>linux-x86_64</netty-transport-native-io_uring-classifier>
280281

281282
<fast-tests>false</fast-tests>
282283

0 commit comments

Comments
 (0)