Обнаружение сбоя соединения RMI при обратном вызове

1

Я пишу распределенное приложение Java RMI. Клиент RMI регистрирует обработчик/обратный вызов события на сервере RMI, и сервер при необходимости вызывает функцию обратного вызова клиента. Теперь проблема заключается в том, что при сбое сетевого подключения (например, кабель Ethernet подключен...) сервер RMI и клиент не будут уведомлены, а сервер RMI не сможет выполнить попытку вызвать зарегистрированную клиентом функцию обратного вызова. RMI сервер также не может оповестить об этом RMI-клиента. Еще хуже то, что при восстановлении сетевого соединения служба клиента RMI все равно теряет связь с сервером RMI, потому что никто не уведомляет ее о повторном подключении.

Моя нынешняя идея - реализовать метод ping() в клиенте RMI в отдельном потоке. Этот поток мог просыпаться с регулярными интервалами и проверять сервер. если не удалось, то фарс для повторного подключения.

Любые другие элегантные решения? Надеюсь, вы, ребята, можете помочь!

интерфейс

import java.rmi.Remote;
import java.rmi.RemoteException;


public interface MyInterface extends Remote {
    public int RegisterEventHandler(RemoteMyEventHandler eventHandler) throws RemoteException;
    public void unRegisterEventHandler(int eventHandlerId) throws RemoteException;
}

Внедрение RMI-сервера

import java.rmi.RemoteException;
import com.me.MyInterface;

public class MyInterfaceImpl  implements MyInterface {
{
     public void init() {
        try {
            //... initialize RMI server....
            //....
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

   @Override
    public int RegisterEventHandler(RemoteMyEventHandler eventHandler)
            throws RemoteException {
        return MyEventHandlerImp.getInstance().addHandler(eventHandler);
    }

    @Override
    public void unRegisterEventHandler(int eventHandlerId)
            throws RemoteException {
        MyEventHandlerImp.getInstance().removeHandler(eventHandlerId);
    }   
}

//handler.notifyEventSnap(events);

внедрение клиента RMI

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Properties;
import org.apache.log4j.Logger;
import com.me.MyInterface;

public class MyService implements NotifyHandler{
{
    private MyInterface client;
    private MyEventHandler myEventHandler;

    private void connectToServer() {
        try {
            //...
            Registry registry = LocateRegistry.getRegistry(rmiHost, rmiPort);
            client = (MyInterface) registry.lookup(MyCInterface.class.getName());
        } catch (RemoteException er) {

        } catch (NotBoundException en) {

        } catch (Exception en) {

        } 
    }

    private void startService(){
           //Attach my event handler
            if(client != null)
            {
                myEventHandler = new MyEventHandler();
                myEventHandlerId = client.RegisterEventHandler(myEventHandler);

            }
    }
}
Теги:
rmi

2 ответа

0

при сбое сетевого подключения (например, кабель Ethernet подключен...) сервер RMI и клиент не будут уведомлены, а сервер RMI не сможет выполнить попытку вызвать зарегистрированную клиентом функцию обратного вызова.

Err, то есть уведомление для сервера. Сервер просто должен отметить это и повторить попытку позже.

Сервер RMI не может уведомить клиента RMI об этой проблеме.

Клиенту не нужно знать.

Еще хуже то, что при восстановлении сетевого соединения служба клиента RMI все равно теряет связь с сервером RMI, потому что никто не уведомляет ее о повторном подключении.

Клиент не должен "повторно подключаться". В RMI отсутствует этап подключения или повторного подключения. Пока клиентские JVM и удаленные объекты остаются и экспортируются соответственно, заглушки на сервере остаются в силе и могут продолжать использоваться сервером.

Вы решаете проблему без проблем.

  • 0
    Я понимаю, откуда ты. Удаленные объекты все еще действительны, пока JVM работает и удаленные объекты экспортируются. Проблема, которую я вижу, состоит в том, что если JVM выходит из строя или удаленный объект не экспортируется, сервер получит то же исключение, что и временное отключение сети. Я не верю, что вы можете различить эти два вопроса, поэтому они должны рассматриваться одинаково. Если это игнорируется, сервер в конечном итоге будет отслеживать удаленные объекты, которые никогда не будут работать, что является утечкой памяти. Проверка связи с клиентами и их удаление после стольких неудачных попыток кажется единственным вариантом.
  • 0
    Если одноранговый узел отключается и поднимается, вы получите NoSuchObjectException, а не исключение подключения, что указывает на устаревшую заглушку, которую обязательно нужно повторно получить. Если заглушка не работает, конечно, она должна быть отброшена и повторно приобретена. Но вы должны позволить себе пару повторных попыток в случае, если условие является переходным. И я ничего не говорил о «игнорировании».
Показать ещё 1 комментарий
0

Кажется, вы частично выполняете сеанс клиент/сервер. Это токен, который сервер может отслеживать, чтобы клиент был действительным. Если есть ошибка, когда сервер общается с клиентом, сеанс должен быть завершен и все ссылки на клиента удалены.

На вашем сервере уже выполняется сеанс с целым числом, используемым для unRegisterEventHandler. Вы должны отслеживать эти целые числа где-то как Карта. Если сервер не может подключиться к клиенту, он должен просто отменить регистрацию этого клиента и сделать сеанс недействительным, удалив его с карты. Сервер должен удалить все ссылки на клиента и не пытаться связываться с клиентом до тех пор, пока не будет создан новый сеанс.

Если клиент пытается связаться с сервером, он должен получить исключение InvalidException с сервера. Таким образом, клиент может попытаться создать новый сеанс, вызвав RegisterEventHandler в блоке catch.

Я работал над проектом, который рассматривал эту проблему, используя пинг, как вы предложили на https://code.google.com/p/umuc-team-factor/

Вся клиентская связь с сервером находилась в замкнутом блоке try catch catch

private void getSession() {
    while(isRun()) {
        try {
            if(server == null) {
                Logger.getLogger(JobClient.class.getName()).info("Server is null.");
                setupServer();
            }
            UUID sid = server.getSession(this);
            synchronized (this) {
                id = sid;
            }
            Logger.getLogger(JobClient.class.getName()).info("Session id is " + id);
            return;
        } catch (RemoteException ex) {
            Logger.getLogger(JobClient.class.getName()).info("Could not get session from server: " + ex + ". setting up server.");
            setupServer();
        }
    }
}

Попробуйте настроить сеанс с сервером до остановки программы.

Вся коммуникация сервера с клиентом должна завершать сеанс для клиента, если возникает исключение RemoteException. c.status() похож на ping.

List<UUID> endSessions = new ArrayList<UUID>();
for (UUID id : copy.keySet()) {
    ClientCallback c = copy.get(id).client;
    try {
        ClientStatus status = c.status();
        Logger.getLogger(ProcessManager.class.getName()).info("got client status for " + id + ": " + status.getSessionID() + " -" + status.getJobStatus());
        if (status.getSessionID() == null || !status.getSessionID().equals(id)) {
            endSessions.add(id);
        }
    } catch (Exception ex) {
        endSessions.add(id);
        Logger.getLogger(ProcessManager.class.getName()).log(Level.SEVERE, null, ex);
    }
}
for (UUID id : endSessions) {
    try {
        endSession(id);
    } catch (SessionExpiredException ex) {
        Logger.getLogger(ProcessManager.class.getName()).log(Level.SEVERE, null, ex);
    }
}
  • 0
    Почему сеанс должен быть закрыт только из-за временного состояния сети? TCP не делает этого; RMI не делает этого; зачем приложение?
  • 0
    Это не должно быть. Моя программа проверяла клиентов каждые 15 секунд. Это зависит от того, как вы определяете временные. Apache tomcat позволяет определить ограничение времени для сеансов. Почему не в этом приложении?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню