1

我有两个通过 RMI 通信的应用程序,一个从服务器(其中会有多个)和一个主服务器。

遵循良好的抽象设计,我想以一种方式实现从站,它不知道在与主站交谈时,它正在使用 RMI(例如,这两个应用程序也可以在同一个 JVM 中运行) :

public static void main(String[] a) {
     Master ms = magicGetTheMasterFromRMI();
     new Slave(ms);
}

...

class Slave {

   public Slave(Master m) {
       m.registerSlave(this); // PROBLEM LINE   
   }

}

问题:上面标记的行PROBLEM LINE不起作用,因为我不能简单地通过它(它Slave本身就是一个RemoteMaster回话的)。我必须明确地做一个UnicastRemoteObject.exportObject(this, 0)(或者toStub(this)如果它是之前导出的),但这会使Slave类依赖于 RMI,从而破坏了设计。

此外,registerSlave迫使我 catch RemoteException,这也增加了 RMI 依赖性。

你会建议什么来解决这些问题?

(这也让我感到困扰,这些类必须实现 Remote,但我想我们只能在抽象方面走这么远)

4

4 回答 4

1

好吧,我已经这样做了:

interface Service {
   void doIt();
}

class ServiceImpl implements Service {
  public void doIt() { ... }
}

interface RemoteService extends Remote {
  void proxyDoIt() throws RemoteException;
}

class RemoteServiceHost implements RemoteService {
  public void proxyDoIt() throws RemoteException {
    // serviceImpl is a field, defined in the constructor
    serviceImpl.doIt();
  }
}

class RemoteServiceClient implements Service {
  public void doIt() {
   try {
    // remoteService is a field, defined in the constructor
    remoteService.proxyDoIt();
   } catch (RemoteException e) {
    throw new RuntimeException(e);
   }
  }
}
于 2010-09-22T08:53:59.407 回答
1

RMI 需要显式导出对象

仅当它们不扩展 UnicastRemoteObject 或 Activatable 时。如果他们这样做,他们会在施工时自动导出。

我必须明确地做一个 UnicastRemoteObject.exportObject(this, 0)

不,见上文。

(或 toStub(this) 如果它是之前导出的)

无论 toStub() 是什么。有一个 RemoteObject.toStub(),但你不能调用它,如果你是在浪费你的时间。

但你根本不必这样做。如果“this”是一个导出的远程对象,您可以将它作为 RMI 参数或结果传递。RMI 将自动替换存根。

于 2010-10-12T05:41:33.383 回答
0

我会警惕这种抽象——远程服务的请求在很多方面与本地服务的请求不同——延迟、故障模式、重试语义。

可能是您的抽象是泄漏的,因为它不是真正有效的。

于 2010-09-15T13:46:27.867 回答
0

您的 Slave 应用程序的某些部分必须准备好通过 RMI 接收呼叫,并处理 RemoteException 等。为什么不在 Slave 和 Master 之间引入某种代理来调解通信并隐藏 RMI 与本地问题. 例如,大致如下:

public Slave(Master m)
{
   new MasterConnection(m, this);
}

class MasterConnection implements Slave extends UnicastRemoteObject
{
   Slave s;

   public MasterConnection(Master m, Slave s) throws IOException
   {
      this.slave = s;
      try {
         exportObject(this);
      } catch (RemoteException e){
         throw new IOException("Could not communicate with Master etc....");
      }
      master.registerSlave(this);
   }

   public void callbackFromMaster(Object arg) // or whatever
   {
      s.callbackFromMaster(arg);
   }
}
于 2010-09-23T15:39:08.393 回答