Проблема при закрытии сервера RMI - PullRequest
0 голосов
/ 06 ноября 2018

При удаленном закрытии RMI-сервера возникают проблемы. В моей программе клиент должен подключиться к серверу промежуточного программного обеспечения RMI, а промежуточное программное обеспечение RMI подключается к 3 различным серверам RMI (flightManager, carManager и roomManager). Клиент может отправить команду выключения промежуточному программному обеспечению. Затем промежуточное программное обеспечение должно отключить 3 сервера и сам. Но после того, как я выключил carManager, промежуточное программное обеспечение немедленно выключилось и оставило в живых 2 других сервера.

Промежуточное программное обеспечение соединяет 3 менеджера и получает заглушки от 3 менеджеров. При получении вызова на отключение выполняет следующую функцию:

public void shutdown() throws RemoteException{
     try{
         this.carManager.shutdown();
         this.flightManager.shutdown();
         this.roomManager.shutdown();
         UnicastRemoteObject.unexportObject(this, true);

         System.out.println("Server exiting.");
        }
        catch(Exception e){}
     System.exit(0);
}

Это код для 3 разных менеджеров, он расширяет ResourceManger и дает промежуточному программному обеспечению заглушку как IResourceManager.

public class RMIResourceManager extends ResourceManager 
{
private static String s_serverName = "Server";
private static String s_rmiPrefix = "test";

public static void main(String args[])
{
    if (args.length > 0)
    {
        s_serverName = args[0];
    }

    // Create the RMI server entry
    try {
        // Create a new Server object
        RMIResourceManager server = new RMIResourceManager(s_serverName);

        // Dynamically generate the stub (client proxy)
        IResourceManager resourceManager = (IResourceManager)UnicastRemoteObject.exportObject(server, 0);

        // Bind the remote object's stub in the registry
        Registry l_registry;
        try {
            l_registry = LocateRegistry.createRegistry(1099);
        } catch (RemoteException e) {
            l_registry = LocateRegistry.getRegistry(1099);
        }
        final Registry registry = l_registry;
        registry.rebind(s_rmiPrefix + s_serverName, resourceManager);

        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                try {
                    registry.unbind(s_rmiPrefix + s_serverName);
                    System.out.println("'" + s_serverName + "' resource manager unbound");
                }
                catch(Exception e) {
                    System.err.println((char)27 + "[31;1mServer exception: " + (char)27 + "[0mUncaught exception");
                    e.printStackTrace();
                }
            }
        });                                       
        System.out.println("'" + s_serverName + "' resource manager server ready and bound to '" + s_rmiPrefix + s_serverName + "'");
    }
    catch (Exception e) {
        System.err.println((char)27 + "[31;1mServer exception: " + (char)27 + "[0mUncaught exception");
        e.printStackTrace();
        System.exit(1);
    }

    // Create and install a security manager
    if (System.getSecurityManager() == null)
    {
        System.setSecurityManager(new SecurityManager());
    }
}

public RMIResourceManager(String name)
{
    super(name);
}
}

И, наконец, класс ResourceManager реализует IResourceManager. В нем есть функция отключения.

public class ResourceManager implements IResourceManager{

        public void shutdown() throws RemoteException{
            System.exit(1);
    }
}

Кажется, любое завершение менеджера вызовет завершение промежуточного программного обеспечения. Функция выключения в промежуточном программном обеспечении исключает строку «this.carManager.shutdown ();» и никогда не оправдывай строки выше. Как я могу справиться с этой проблемой?

На рисунках показана проблема: клиент вводит «выключение». Затем carManager выключается, и промежуточное программное обеспечение немедленно выключается. FlightManager и roomManager остаются в живых. enter image description here

1 Ответ

0 голосов
/ 06 ноября 2018

Я думаю, что ваша проблема в том, что ваша реализация shutdown () на самом деле отключает сервер в середине взаимодействия с его клиентом - поэтому клиентская заглушка видит, что соединение обрывается, и выдает исключение (которое вы видите на ваш снимок экрана) - который прерывает работу этого клиента, прежде чем он попытается завершить работу двух других.

Вы хотели бы реализовать свои серверы таким образом, чтобы при вызове shutdown () вы отменили регистрацию этого сервера (чтобы клиентские подключения больше не принимались), а затем запустили отложенный поток, чтобы фактически закрыть приложение - таким образом, вызов, по которому вы находитесь, будет нормально возвращаться клиенту, который затем сможет продолжить.

В качестве альтернативы, я полагаю, вы можете заключить каждый из трех вызовов shutdown () в try / catch, так что вы можете игнорировать исключение, которое выдает каждый клиент, и переходить к следующему серверу, чтобы он отключился ...

...