题 本地JVM之间的通信


我的问题: 可以/应该采取什么方法在本地运行的两个或多个JVM实例之间进行通信?

问题的一些描述:
我正在为一个项目开发一个系统,该系统需要单独的JVM实例来完全隔离某些任务。

在它运行时,'父'JVM将创建它将期望执行的'子'JVM,然后将结果返回给它(以相对简单的POJO类或结构化XML数据的格式)。不应使用SysErr / SysOut / SysIn管道传输这些结果,因为孩子可能已经将这些结果用作其运行的一部分。

如果子JVM在一定时间内没有响应结果,则父JVM应该能够通知子进程停止处理或终止子进程。否则,子JVM应在完成其任务结束时正常退出。

迄今为止的研究:
我知道有许多技术可能有用,例如....

  • 使用Java的RMI库
  • 使用套接字传输对象
  • 使用Cajo,Hessian等分发库

...但我有兴趣听取其他人在推行其中一种方案或其他方案之前可能会考虑的方法。

感谢您对此提供任何帮助或建议!

编辑:
转移的数据量 -  相对较小,它将主要是少数包含字符串的POJO,这些字符串将代表子项执行的结果。如果任何解决方案在大量信息上效率低下,那就是 不会 成为我系统中的一个问题。转移的金额应该是非常静态的,所以这样做  必须是可扩展的。

转移延迟 -  在这种情况下不是一个关键的问题,虽然如果需要对结果进行任何“轮询”,这应该能够相当频繁而没有显着的开销,因此我可以在以后维护响应式GUI(例如进度条)


24
2018-02-19 16:48


起源


也许你可以谈谈你需要传输多少数据以及它对延迟有多重要?除非您有明显的性能限制,否则您认为最简单的解决方案可能是最好的。 - Peter Lawrey
@Peter Lawrey我为你添加了一些额外的细节,谢谢! - obfuscation


答案:


我用了 KryoNet 使用本地套接字,因为它专门用于序列化并且非常轻量级(你也可以使用远程方法调用!我现在正在使用它),但禁用套接字断开超时。

RMI基本上基于您具有远程类型并且远程类型实现接口的原则。此接口是共享的。在本地计算机上,通过RMI库将接口绑定到RMI库中的“inject”内存代码,结果是您拥有满足接口但能够与远程对象通信的内容。


5
2018-02-19 18:03



这看起来非常有趣,可能确实满足了我的需求。是否有一些方面你发现它完全缺乏它,即使这些方面目前没有引起任何问题? - obfuscation
一些问题与网络类的注册和初始注册的竞争条件有关。但是可以通过确保方法调用以正确的顺序完成来克服这些问题。此外,我发现连接时有时会使连接饱和(我在网络模拟器界面上运行),并且它给出的一些错误令人困惑,很难确定原因。 - Chris Dennett
另一件事:很难获得调用方法的连接,但我正在修改kryonet并添加该功能。如果我只是让客户说谎他们来自哪个联系,那么所有的破坏都可能会破裂。 - Chris Dennett
我只是想说一下启用RMI的小源代码如何 - 它基本上是600行代码。什么都没有。但它的效果非常好。 - Chris Dennett
另一件事:它不支持一对多RMI调用(因此,如果调用远程方法,它会在100个远程对象上调用相同的方法)。 - Chris Dennett


不是直接回答你的问题,而是建议替代方案。 你有没有考虑过 OSGI

它允许您在SAME jvm中彼此完全隔离地运行Java项目。 它的美妙之处在于项目之间的沟通非常容易与服务(见 核心规格PDF 第123页)。这种方式没有任何类型的“序列化”,因为数据和调用都在同一个jvm中。

此外,您对服务质量(响应时间等)的所有要求都消失了 - 您只需要担心在您想要使用它时服务是UP还是DOWN。为此你有一个非常好的规范,为你做这个叫做声明式服务(参见 企业规范PDF 第141页)

对于非主题回答感到抱歉,但我认为其他人可能会认为这是另一种选择。

更新 

要回答有关安全性的问题,我从未考虑过这种情况。我不相信有一种方法可以在OSGI中强制执行“内存”使用。

但是,有一种在不同OSGI运行时之间在JVM之外进行通信的方法。它被称为远程服务(请参阅 企业规范PDF,第7页)。他们也很好地讨论了在做类似事情时需要考虑的因素(见13.1谬误)。

Apache Felix的人(OSGI的实现)我认为可以用iPOJO实现这个,叫做 使用iPOJO的分布式服务 (他们的包装使得使用服务更容易)。我从来没有用过这个 - 所以如果我错了就不理我。


6
2018-02-19 18:16



不需要道歉,这是一个有趣的建议。我面临的一个问题是子JVM执行的部分代码是不可信的,因此必须加以限制(例如通过安全管理器)。作为其中的一部分,我需要限制内存使用量以确保父JVM有足够的资源可用。但是,根据我的发现,我不能限制JVM中的内存使用,以防止内存不足异常。 OSGI是否对此提供任何保护/监管? - obfuscation
我已经回复了这个问题。 - drozzy


阿卡 是另一种选择,以及 其他java actor框架,它提供了来自的传播和其他好东西 演员模特


5
2018-02-19 21:12





如果你不能使用stdin / stdout,那么我会使用套接字。你需要在套接字之上使用某种序列化层(就像使用stdin / stdout一样),而RMI是一个非常易于使用且非常有效的层。

如果您使用RMI并发现性能不够好,我会切换到一些更高效的序列化器 - 有 有很多选择

我不会去任何Web服务或XML附近。这似乎完全浪费时间,可能需要更多的努力并提供比RMI更低的性能。


4
2018-02-19 17:59



谢谢,我相信这是我倾向的方向。由于传输的数据量相对较小,我相信我不应该面对任何真正的性能问题,但如果这确实成为问题,我会记下您的链接。 - obfuscation


似乎没有多少人喜欢RMI了。

选项:

  1. 网页服务。例如 http://cxf.apache.org
  2. JMX。现在,这实际上是在表格下使用RMI的一种方法,但它可以工作。
  3. 其他IPC协议;你引用了Hessian
  4. 使用套接字甚至共享内存自行滚动。 (在父级中打开一个映射文件,在子级中再次打开它。你仍然需要一些东西进行同步。)

注意事项的例子是Apache ant(为各种目的分配各种Jvms),Apache maven以及Tanukisoft daemonization kit的开源变体。

就个人而言,我非常容易使用网络服务,所以这就是我倾向于把东西变成钉子的锤子。典型的JAX-WS + JAX-B或JAX-RS + JAX-B服务是CXF的非常少的代码,并为我管理所有数据序列化和反序列化。


3
2018-02-19 17:17



出于兴趣,你的偏好在哪里?我很感激,当你只对上面的项目进行简短描述时,这可能有点难以理解。 - obfuscation


上面提到过,但我想对JMX的建议进行一些扩展。我们实际上正在做的正是你打算做的事情(从我可以从你的各种评论中收集到的)。我们出于各种原因使用jmx,其中一些我会在这里提到。首先,jmx是关于管理的,所以一般来说它非常适合你想要做的事情(特别是如果你已经计划为其他管理任务提供jmx服务)。你在jmx接口中所做的任何努力都将扮演双重责任,因为你可以使用jvisualvm之类的java管理工具调用它。这导致了我的下一点,这与你想要的最相关。新的 附加API 在jdk 6及以上是非常甜蜜的。它使您能够动态发现并与正在运行的jvms通信。例如,这允许您的“控制器”进程崩溃并重新启动并重新查找所有现有的工作进程。这是一个非常强大的系统的材料。上面提到jmx基本上是rmi,但是,与直接使用rmi不同,您不需要管理所有连接细节(例如处理独特端口,可发现性等)。 attach api在jdk中是一个隐藏的宝石,因为它没有很好的记录。当我最初开始研究这个东西时,我不知道api的名字,所以想想jvisualvm和jconsole中的“魔法”是如何工作的非常困难。最后,我偶然发现了一篇文章 这个,它显示了如何实际 使用 在您自己的程序中动态附加api。


3
2018-02-20 03:05



附加api仅适用于子进程ID。生成子进程后,需要获取进程ID。 - Dead Programmer
@SureshSankar - 你不需要知道附加到进程的pid,但它确实有帮助。 - jtahlborn
如果您不知道子进程ID,您将如何控制或调用子进程中的方法。让我知道如何连接到没有进程ID的子进程。 - Dead Programmer
@SureshSankar - 正如我在回答中所说,attach api允许你动态发现其他java进程。如果你有办法识别你的子进程,你可以在不知道他们的pid的情况下找到它们(这就是我们的产品的工作方式)。 - jtahlborn


虽然它是为JVM之间的潜在远程通信而设计的,但我想你会发现它 网状 在本地JVM实例之间也能很好地工作。

它可能是Java类型中性能最高/最强大/最广泛支持的库。


2
2018-02-19 18:12



Netty肯定看起来非常高,但在我看来,它的专长是略有不同的问题。您是否尝试过以这种方式使用Netty?此外,根据您的经验,它似乎可能略微超重 - 从您的经验来看,学习/使用需要大量投资吗? - obfuscation
它确实需要一些设置 - 虽然一旦你使它工作它坚如磐石。如果你真的在寻找更轻量级的东西,我可能会推荐KryoNet - mikera


上面讨论了很多。但无论是套接字,rmi,jms - 都涉及到一些肮脏的工作。 我会提出建议 阿卡。它是基于actor的模型,它使用Messages进行相互通信。

美女是,演员可以在同一个JVM或另一个(非常小的配置)和akka照顾其余的你。我还没有看到比这更干净的方式:)


2
2018-05-09 09:23