有一些 IPC 库可以通过 Java 中的内存映射文件促进共享内存的使用。
Chronicle Queue 类似于非阻塞 Java Queue,除了您可以在一个 JVM 中提供消息并在另一个 JVM 中轮询它。
在两个 JVM 中,您应该在同一个 FS 目录中创建一个 ChronicleQueue 实例(如果您不需要消息持久性,请将此目录放在内存挂载的 FS 中):
ChronicleQueue ipc = ChronicleQueueBuilder.single("/dev/shm/queue-ipc").build();
在一个 JVM 中写入消息:
ExcerptAppender appender = ipc.acquireAppender();
appender.writeDocument(w -> {
w.getValueOut().object(message);
});
在另一个 JVM 中读取消息:
ExcerptTailer tailer = ipc.createTailer();
// If there is no message, the lambda, passed to the readDocument()
// method is not called.
tailer.readDocument(w -> {
Message message = w.getValueIn().object(Message.class);
// process the message here
});
// or avoid using lambdas
try (DocumentContext dc = tailer.readingDocument()) {
if (dc.isPresent()) {
Message message = dc.wire().getValueIn().object(Message.class);
// process the message here
} else {
// no message
}
}
Aeron 不仅仅是 IPC 队列(它是一个网络通信框架),它还提供 IPC 功能。它类似于 Chronicle Queue,一个重要的区别是它使用 SBE 库进行消息编组/解组,而 Chronicle Queue 使用 Chronicle Wire。
Chronicle Map 允许通过某个键进行 IPC 通信。在两个 JVM 中,您应该创建一个具有相同配置的映射并持久化到同一个文件(如果您不需要实际的磁盘持久性,则该文件应该本地化到内存挂载的 FS 中,例如在 /dev/shm/ 中):
Map<Key, Message> ipc = ChronicleMap
.of(Key.class, Message.class)
.averageKey(...).averageValue(...).entries(...)
.createPersistedTo(new File("/dev/shm/jvm-ipc.dat"));
然后你可以在一个 JVM 中编写:
ipc.put(key, message); // publish a message
在接收方 JVM 上:
Message message = ipc.remove(key);
if (message != null) {
// process the message here
}