java 本地JVM之间的通信

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5052102/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 09:11:36  来源:igfitidea点击:

Communication between local JVMs

javasocketsjvmrmicajo

提问by obfuscation

My question:What approach could/should I take to communicate between two or more JVM instances that are running locally?

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

Some description of the problem:
I am developing a system for a project that requires separate JVM instances to isolate certain tasks from each other entirely.

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

In it's running, the 'parent' JVM will create 'child' JVMs that it will expect to execute and then return results to it (in the format of relatively simple POJO classes, or perhaps structured XML data). These results should not be transferred using the SysErr/SysOut/SysIn pipes as the child may already use these as part of its running.

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

If a child JVM does not respond with results within a certain time, the parent JVM should be able to signal to the child to cease processing, or to kill the child process. Otherwise, the child JVM should exit normally at the end of completing its task.

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

Research so far:
I am aware there are a number of technologies that may be of use e.g....

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

  • Using Java's RMI library
  • Using sockets to transfer objects
  • Using distribution libraries such as Cajo, Hessian
  • 使用 Java 的 RMI 库
  • 使用套接字传输对象
  • 使用 Cajo、Hessian 等分发库

...but am interested in hearing what approaches others may consider before pursuing one of these options, or any others.

...但我有兴趣了解其他人在追求这些选择之一或任何其他选择之前可能会考虑的方法。

Thanks for any help or advice on this!

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

Edits:
Quantity of data to transfer-relatively small, it will mostly be just a handful of POJOs containing strings that will represent the result of the child executing. If any solution would be inefficient on larger amounts of information, this is unlikelyto be a problem in my system. The amount being transferred should be pretty static and so this does nothave to be scalable.

编辑:
要传输的数据量-相对较小,主要是少数包含表示子执行结果的字符串的 POJO。如果任何解决方案在大量信息上效率低下,这在我的系统中不太可能成为问题。被转移的量应该是相当静态的,因此这并没有必须具有可扩展性。

Latency of transfer-not a critical concern in this case, although if any 'polling' of results is needed this should be able to be fairly frequent without significant overheads, so I can maintain a responsive GUI on top of this at a later time (e.g. progress bar)

传输延迟 -在这种情况下不是关键问题,尽管如果需要对结果进行任何“轮询”,这应该能够相当频繁地进行,而不会产生大量开销,因此我可以稍后在此之上维护响应式 GUI(例如进度条)

采纳答案by Chris Dennett

I'd use KryoNetwith local sockets since it specialises heavily in serialisation and is quite lightweight (you also get Remote Method Invocation! I'm using it right now), but disable the socket disconnection timeout.

我将KryoNet与本地套接字一起使用,因为它专注于序列化并且非常轻量级(您还可以获得远程方法调用!我现在正在使用它),但禁用套接字断开连接超时。

RMI basically works on the principle that you have a remote type and that the remote type implements an interface. This interface is shared. On your local machine, you bind the interface via the RMI library to code 'injected' in-memory from the RMI library, the result being that you have something that satisfies the interface but is able to communicate with the remote object.

RMI 的基本工作原理是您有一个远程类型并且远程类型实现了一个接口。这个接口是共享的。在您的本地机器上,您通过 RMI 库将接口绑定到 RMI 库中“注入”内存中的代码,结果是您拥有满足接口但能够与远程对象通信的内容。

回答by Andriy Drozdyuk

Not directly an answer to your question, but a suggestion of an alternative. Have you considered OSGI?

不是直接回答您的问题,而是对替代方案的建议。你考虑过OSGI吗?

It lets you run java projects in complete isolation from each other, within the SAME jvm. The beauty of it is that communication between projects is very easy with services (see Core Specifications PDFpage 123). This way there is not "serialization" of any sort being done as the data and calls are all in the same jvm.

它使您可以在 SAME jvm 中彼此完全隔离地运行 java 项目。它的美妙之处在于项目之间的通信非常容易与服务(参见核心规范 PDF第 123 页)。这样就不会进行任何类型的“序列化”,因为数据和调用都在同一个 jvm 中。

Furthermore all your requirements of quality of service (response time etc...) go away - you only have to worry about whether the service is UP or DOWN at the time you want to use it. And for that you have a really nice specification that does that for you called Declarative Services (See Enterprise Spec PDFpage 141)

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

Sorry for the off-topic answer, but I thought some other people might consider this as an alternative.

对于题外话的回答很抱歉,但我认为其他一些人可能会认为这是另一种选择。

Update

更新

To answer your question about security, I have never considered such a scenario. I don't believe there is a way to enforce "memory" usage within OSGI.

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

However there is a way of communicating outside of JVM between different OSGI runtimes. It is called Remote Services (see Enterprise Spec PDF, page 7). They also have nice discussion there of the factors to take into consideration when doing something like that (see 13.1 Fallacies).

然而,有一种方法可以在 JVM 之外的不同 OSGI 运行时之间进行通信。它称为远程服务(参见Enterprise Spec PDF,第 7 页)。他们也对在做类似事情时要考虑的因素进行了很好的讨论(参见 13.1 谬误)。

Folks at Apache Felix (implementation of OSGI) I think have implementation of this with iPOJO, called Distributed Services with iPOJO(their wrapper to make using services easier). I've never used this - so ignore me if I am wrong.

Apache Felix 的人们(OSGI 的实现)我认为使用 iPOJO 实现了这一点,称为带有 iPOJO 的分布式服务(它们的包装器使使用服务更容易)。我从来没有用过这个——所以如果我错了,请忽略我。

回答by superfav

akkais another option, as well as other java actor frameworks, it provides communication and other goodies derived from the actor model.

akka是另一种选择,以及其他 Java 演员框架,它提供从演员模型派生的通信和其他好处。

回答by Tom Anderson

If you can't use stdin/stdout, then i'd go with sockets. You need some sort of serialization layer on top of the sockets (as you would with stdin/stdout), and RMI is a very easy to use and pretty effective such layer.

如果您不能使用标准输入/标准输出,那么我会使用套接字。您需要在套接字顶部使用某种序列化层(就像使用 stdin/stdout 一样),而 RMI 是一个非常易于使用且非常有效的此类层。

If you used RMI and found the performance wasn't good enough, i'd switch to some more efficient serializer - there are plenty of options.

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

I wouldn't go anywhere near web services or XML. That seems like a complete waste of time, likely take more effort and deliver less performance than RMI.

我不会靠近 Web 服务或 XML。这似乎完全是在浪费时间,与 RMI 相比,它可能需要更多的努力并提供更少的性能。

回答by jtahlborn

It was mentioned above, but i wanted to expand a bit on the JMX suggestion. we actually are doing pretty much exactly what you are planning to do (from what i can glean from your various comments). we landed on using jmx for a variety of reasons, a few of which i'll mention here. for one thing, jmx is all about management, so in general it is a perfect fit for what you want to do (especially if you already plan on having jmx services for other management tasks). any effort you put into jmx interfaces will do double duty as apis you can call using java management tools like jvisualvm. this leads to my next point, which is the most relevant to what you want. the new Attach APIin jdk 6 and above is very sweet. it enables you to dynamically discover and communicate with running jvms. this allows, for example, for your "controller" process to crash and restart and re-find all the existing worker processes. this is the makings of a very robust system. it was mentioned above that jmx basically rmi under the hood, however, unlike using rmi directly, you don't need to manage all the connection details (e.g. dealing with unique ports, discoverability, etc). the attach api is a bit of a hidden gem in the jdk, as it isn't very well documented. when i was poking into this stuff initially, i didn't know the name of the api, so figuring how the "magic" in jvisualvm and jconsole worked was very difficult. finally, i came across an article like this one, which shows how to actually usethe attach api dynamically in your own program.

上面提到过,但我想对 JMX 建议进行一些扩展。我们实际上正在做您计划做的事情(从我从您的各种评论中了解到的情况)。我们出于各种原因开始使用 jmx,我将在此处提及其中的几个。一方面,jmx 是关于管理的,所以总的来说它非常适合您想要做的事情(特别是如果您已经计划将 jmx 服务用于其他管理任务)。您在 jmx 接口中所做的任何努力都将起到双重作用,因为您可以使用 jvisualvm 之类的 Java 管理工具调用 API。这引出了我的下一点,这与您想要的最相关。新的附加 API在 jdk 6 及以上是非常甜蜜的。它使您能够动态发现正在运行的 jvm 并与之通信。例如,这允许您的“控制器”进程崩溃并重新启动并重新找到所有现有的工作进程。这是一个非常强大的系统的组成部分。上面提到过,jmx 在底层基本上是 rmi,但是,与直接使用 rmi 不同,您不需要管理所有连接细节(例如,处理唯一端口、可发现性等)。附加 api 在 jdk 中有点像隐藏的宝石,因为它没有很好的文档记录。当我最初研究这些东西时,我不知道 api 的名称,因此弄清楚 jvisualvm 和 jconsole 中的“魔法”是如何工作的非常困难。最后,我读到一篇文章,像这一个在您自己的程序中动态使用附加 api。

回答by bmargulies

Not many people seem to like RMI any longer.

似乎没有多少人不再喜欢 RMI。

Options:

选项:

  1. Web Services. e.g. http://cxf.apache.org
  2. JMX. Now, this is really a means of using RMI under the table, but it would work.
  3. Other IPC protocols; you cited Hessian
  4. Roll-your-own using sockets, or even shared memory. (Open a mapped file in the parent, open it again in the child. You'd still need something for synchronization.)
  1. 网页服务。例如http://cxf.apache.org
  2. JMX。现在,这确实是一种在表下使用 RMI 的方法,但它会起作用。
  3. 其他 IPC 协议;你引用了Hessian
  4. 自己使用套接字,甚至共享内存。(在父级中打开一个映射文件,在子级中再次打开它。你仍然需要一些东西来同步。)

Examples of note are Apache ant (which forks all sorts of Jvms for one purpose or another), Apache maven, and the open source variant of the Tanukisoft daemonization kit.

值得注意的例子是 Apache ant(它为一个或另一个目的分叉各种 Jvm)、Apache maven 和 Tanukisoft 守护程序工具包的开源变体。

Personally, I'm very facile with web services, so that's the hammer which which I tend to turn things into nails. A typical JAX-WS+JAX-B or JAX-RS+JAX-B service is very little code with CXF, and manages all the data serialization and deserialization for me.

就我个人而言,我对网络服务非常熟练,所以这就是我倾向于把事情变成钉子的锤子。一个典型的 JAX-WS+JAX-B 或 JAX-RS+JAX-B 服务是用 CXF 编写的很少的代码,并为我管理所有的数据序列化和反序列化。

回答by Jatin

A lot is discussed above. But be it sockets, rmi, jms - there is a lof of dirty work involved. I would ratter advice akka. It is a actor based model which communicate with each other using Messages.

上面讨论了很多。但无论是套接字、rmi、jms - 都涉及到很多肮脏的工作。我会喋喋不休的建议akka。它是一个基于参与者的模型,它使用消息相互通信。

The beauty is, the actors can be on same JVM or another (very little config) and akka takes care the rest for you. I haven't seen a more cleaner way than doing this :)

美妙之处在于,actor 可以在同一个 JVM 或另一个(很少的配置)上,而 akka 会为您处理其余的事情。我还没有看到比这样做更干净的方法:)

回答by mikera

Although it's designed for potentially remote communication between JVMs, I think you'll find that Nettyworks extremely well between local JVM instances as well.

尽管它是为 JVM 之间潜在的远程通信而设计的,但我认为您会发现Netty在本地 JVM 实例之间也能很好地工作。

It's probably the most performant / robust / widely supported library of its type for Java.

它可能是同类 Java 中性能最高/最健壮/最受广泛支持的库。

回答by zengr

Try out jGroupsif the data to be communicated is not huge.

如果要通信的数据不是很大,请尝试使用jGroups

回答by Niclas

As you mentioned you can obviously send the objects over the network but that is a costly thing not to mention start up a separate JVM.

正如您所提到的,您显然可以通过网络发送对象,但这是一件代价高昂的事情,更不用说启动一个单独的 JVM。

Another approach if you just want to separate your different worlds inside one JVM is to load the classes with different classloaders. ClassA@CL1!=ClassA@CL2 if they are loaded by CL1 and CL2 as sibling classloaders.

如果您只想在一个 JVM 中分离不同的世界,另一种方法是使用不同的类加载器加载类。ClassA@CL1!=ClassA@CL2 如果它们由 CL1 和 CL2 作为同级类加载器加载。

To enable communications between classA@CL1 and classA@CL2 you could have three classloaders.

要启用 classA@CL1 和 classA@CL2 之间的通信,您可以使用三个类加载器。

  • CL1 that loads process1
  • CL2 that loads process2 (same classes as in CL1)
  • CL3 that loads communication classes (POJOs and Service).
  • 加载 process1 的 CL1
  • 加载 process2 的 CL2(与 CL1 中的类相同)
  • 加载通信类(POJO 和服务)的 CL3。

Now you let CL3 be the parent classloader of CL1 and CL2.

现在让 CL3 成为 CL1 和 CL2 的父类加载器。

In classes loaded by CL3 you can have a light-weight communication send/receive functionality (send(Pojo)/receive(Pojo)) the POJOs between classes in CL1 and classes in CL2.

在 CL3 加载的类中,您可以拥有轻量级通信发送/接收功能(发送(Pojo)/接收(Pojo))CL1 中的类和 CL2 中的类之间的 POJO。

In CL3 you expose a static service that enables implementations from CL1 and CL2 register to send and receive the POJOs.

在 CL3 中,您公开了一个静态服务,该服务使 CL1 和 CL2 寄存器的实现能够发送和接收 POJO。