代码之家  ›  专栏  ›  技术社区  ›  okutane

我对Java进程通信有哪些选择?

  •  2
  • okutane  · 技术社区  · 15 年前

    我们在这种形式的代码中有一个位置:

    void processParam(Object param)
    {
       wrapperForComplexNativeObject result = jniCallWhichMayCrash(param);
       processResult(result);
    }
    

    processParam-用许多不同参数调用的方法。

    JnicallWhichmayCrash-一种本机方法,用于对其参数进行一些复杂的处理,并创建一些复杂的对象。在某些情况下,它可能会崩溃。

    WrapperForComplexNativeObject-Swig生成的包装类型

    过程结果-一种纯Java编写的方法,它通过创建对象的几种类型来处理它的参数(我不是指类,也可能类似于层次结构):
    1-一些相互引用的非唯一对象(来自同一层次结构),这些对象可以具有从具有不同参数值的processParam()方法调用创建的重复项。因为保存所有副本的成本很高,所以有必要缓存它们。
    2-一些相互引用的独特对象(来自同一层次结构)和一些第一类对象。

    对某个集合中的每个参数执行processParam之后,在processResult中创建的数据将一起处理。问题实际上是Jnicallwhichmaycrash方法可能会使整个JVM崩溃,这将是非常糟糕的。崩溃的原因可能是因为一个参数值而不是另一个参数值。我们已经决定最好忽略JVM内部的崩溃,并在这种崩溃发生时跳过一些数据块。为了做到这一点,我们应该在单独的进程内部运行processparam函数,并以某种方式传递结果。 (如何)?怎样?!这是个问题) 对于主进程,如果发生崩溃,我们只会丢失部分数据(没关系),而不会丢失其他所有数据。因此,目前的主要问题是实现不同流程之间的传输。我有哪些选择?我可以考虑通过流进行二进制数据的序列化和传输,但是由于对象的复杂性,序列化可能不是很快。也许我还有其他的选择来实现这个?

    3 回复  |  直到 13 年前
        1
  •  1
  •   Stephen C    13 年前

    让我们假设流程在同一台机器上。您的选择包括:

    • 使用process.exec()为每个请求启动一个新进程,将参数对象作为命令行参数传递,或者通过进程标准输入并从THR进程标准输出读取结果。进程在完成单个请求时退出。

    • 使用process.exec()启动一个长时间运行的进程,使用进程的标准输入/输出发送请求和响应。进程实例处理多个请求。

    • 使用“命名管道”向现有本地(或可能远程)进程发送请求/响应。

    • 使用原始TCP/IP套接字或UNIX域套接字将请求/响应发送到现有的本地(或可能是远程)进程。

    对于上述每一项,您都需要设计自己的请求格式,并在两侧处理参数/结果编码和解码。

    • 将该过程实现为Web服务,并使用JSON或XML(或其他东西)对参数和结果进行编码。根据选定的编码方案,将有现有的库处理编码/解码和(可能)映射到Java类型。

    • SOAP/WSDL——通过这些,通常可以在更高的抽象级别上设计应用程序协议,框架库负责编码/解码、调度请求等。

    • CORBA或类似的冰。这些选项类似于SOAP/WSDL,但使用更有效的线表示等。

    • 消息队列系统,如MQ系列。

    注意,最后四个通常用于客户机和服务器位于不同机器上的系统中,但是当客户机和服务器并置时,它们也可以工作得很好(可能更快)。


    我也许应该补充一下,另一种方法是去掉有问题的JNI代码。要么用纯Java代码替换它,要么将它作为外部命令或服务运行,而不需要Java封装器围绕它。

        2
  •  0
  •   Riduidel    15 年前

    你有没有想过使用网络启发的方法?在您的情况下,通常,Web服务可以/将是一个具有所有多样性的解决方案:

        3
  •  0
  •   Raymond Kroeker    15 年前

    如果您可以隔离流程的责任,即p1是数据的生产者,p2是消费者,那么最可靠的答案是使用文件来通信您的数据。Seralization/反序列化过程中存在开销(读CPU周期),但是您的进程不会崩溃,并且非常容易调试/同步。