RMI java.rmi.NoSuchObjectException和重并发的端口重用

时间:2015-09-24 08:11:42

标签: rmi

我正在开发一个具有以下结构的应用程序

应用程序设计:

  • 一台机器说MACHINE1运行了6种不同的JVM。每个JVM都在其中运行APP1。因此,MACHINE1共有6个并行执行java应用程序APP1
  • 另一台机器MACHINE2运行单JVM,其中运行应用程序APP2。
  • APP2有不同类型的JAVA服务库,如Service1,Service2和service3等。如果任何APP1的MACHINE1想要执行Service1,那么它将调用APP2的Same实例并传递Request Object。 APP2读取Request对象,并在此基础上调用所请求的服务并将结果返回给APP1。
  • APP2的服务使用APP1的xml文件形式的输入数据。所以我们以文件InputStream

  • 的形式将APP1的数据传输到APP2
  • APP1和APP2正在使用RMI进行通信。 APP2的服务在APP1 xml文件上执行操作以生成结果。要从APP1发送数据到APP2,我们选择一个MACHINE1端口并导出输入流的远程对象。在Machine1中,我们维护整数POOL,它指的是Ports。 APP1从池中选择一个端口整数并导出inputStream(我们创建了RMIInputStream)。

问题:

当我们以较少的并发性执行应用程序时,它工作正常。但是当我们增加并发性时,我们开始得到以下异常 " java.rmi.NoSuchObjectException:表中没有这样的对象" 当我们从RemoteInputStream读取数据时会出现此异常。

我试图解决这个问题,并专注于RemoteInputStream对象。我看过很多关于远程对象弱引用的回复。我已经看过它,发现在我的情况下参考并不弱。

我还通过增加租约值修改了dfc属性,但在我的情况下没有效果。

我对这个问题的观察:

在测试期间,我观察到如果所有端口都使用一次,那么每件事都可以正常工作。假设如果我在池中分配20个端口,那么在前20次中我不会得到任何异常。当我第二次开始使用相同的端口时,我会遇到异常。如果我将端口数从20增加到600,那么我将不会在前600次中获得异常。看起来有一些问题是端口重用。 我在将端口整数发送回池之前添加了1分钟的等待时间。在这种情况下,我的问题急剧减少。

所以我的结论是,如果我在MACHINE1的端口输出一个输入Stream对象,说55800和MACHINE2将快速读取它,APP1取消导出数据并再次尝试导出另一个远程输入Stream对象,那么它将产生问题。

我需要所有专家对我的问题进行观察。这个问题与TCP / IP协议有关吗?我是否尝试重用在TCP / IP生命周期方面仍处于活动状态的相同端口? 有没有什么好方法可以解决这个问题,而不是在返回端口中引入Wait。

在MACHINE1的生产环境中,我们已经分配了一定范围的端口整数。我们的应用程序只允许使用此范围之间的端口。防火墙对此特定范围的端口开放。因此,当我们想要导出inputStream时,我们必须确保数据应该在允许的端口范围内导出。所以我们使用以下代码

UnicastRemoteObject.exportObject(remoteInputStreamObj, portNo.intValue());

为此,我们开发了一个POOL来维护自由端口整数。如果在APP1中创建新线程并且有3个XML文件应该在APP2处理,那么APP1将创建一个请求对象并创建新的三个RemoteInputStream对象。在创建对象3端口时,将从池中删除整数。一旦请求在APP2端得到处理并且APP1得到了结果,那么APP1将取消导出该对象并将Ports整数返回给POOL。

此处,端口POOL表示维护空闲端口整数的整数池。此池不表示RemoteInputStream对象池。我们每次创建RemoteInputStream的新实例。在MACHINE1中,当6个JVM正在运行时,我们有另外的第7个JVM,它维护Port POOL的单例引用。因此,所有其他APP1 JVM共享一个POOL实例。

在我们的例子中,我们具有高水平的并发性。除了并发之外,APP1的一个请求可以有多个XML。在少数情况下,单个请求中可以有25-30个文件,需要同时由MACHINE2 APP2读取。在这种情况下,我们需要创建25-30个RemoteInputStream对象实例并将其放在Request Object中。所以这里我们一次需要多个端口。

在实际生产环境中,可能会发生Service1的50个线程同时执行,每个Request Object可能有2-3个inputStream对象需要导出的XML文件。在这种情况下,我们需要多个端口。

1 个答案:

答案 0 :(得分:1)

  

我们开始得到以下异常“java.rmi.NoSuchObjectException:表中没有这样的对象”

这个例外只有一个含义。您试图通过存根调用远程方法,该存根的相应远程对象已取消导出。

  

一旦请求在APP2端得到处理并且APP1得到了结果,那么APP1将取消导出该对象并将Ports整数返回给POOL。

如上所述,这里是问题的根源。你是出口物品。然后一些客户端在远程对象已被取消导出的存根上调用方法,因此您得到此异常,完全如上所述。

您不需要所有这些复杂性。您可以为每个JVM使用单个端口用于所有RMI对象。您甚至不需要取消导出远程对象,这是造成原始问题的原因。只需让它们在正常的事件过程中成为DGC。

抛弃所有这些并按要求返回新的RemoteInputStream