Предложить шаблон проектирования для реализации механизма отработки отказа - PullRequest
1 голос
/ 24 февраля 2012

У меня есть приложение (скажем, App1), которое подключено к другому приложению (App2) через .net remoting. App2 действует как сервер. Если App2 выходит из строя, App1 не сможет получать данные из App2. Мы планируем запустить экземпляр App2 (скажем, App2a) на другом компьютере, так что, если App2 выйдет из строя, App1 автоматически получит данные из App2a. Когда приложение 2 снова запустится. Приложение 1 должно будет взять данные из приложения App2. Механизм отработки отказа еще не реализован ... Пожалуйста, предложите шаблон проектирования, чтобы в будущем можно было добавить любое количество экземпляров сервера для App1 для извлечения данных.

Спасибо

1 Ответ

1 голос
/ 16 января 2013

Самый близкий шаблон проектирования, о котором я могу подумать, это шаблон Цепочки ответственности.

Идея состоит в том, что:

  1. Вы строите цепочку объектов (серверов)
  2. Пусть объект (сервер) обработает запрос
  3. Если это невозможно, передайте запрос по цепочке

Код:

// Server interface
public interface IServer
{
    object FetchData(object param);
}

public class ServerProxyBase: IServer
{
    // Successor.
    // Alternate server to contact if the current instance fails.
    public ServerBase AlternateServerProxy { get; set; }

    // Interface
    public virtual object FetchData(object param)
    {
        if (AlternateServerProxy != null)
        {
            return AlternateServerProxy.FetchData(param);
        }
        throw new NotImplementedException("Unable to recover");
    }
}

// Server implementation
public class ServerProxy : ServerProxyBase
{
    // Interface implementation
    public override object FetchData(object param)
    {
        try
        {
            // Contact actual server and return data
            // Remoting/WCF code in here...
        }
        catch
        {
            // If fail to contact server, 
            // run base method (attempt to recover)
            return base.FetchData(param);
        }
    }
}

public class Client
{
    private IServer _serverProxy;
    public Client()
    {
        // Wire up main server, and its failover/retry servers
        _serverProxy = new ServerProxy("mainserver:2712")
        {
            AlternateServerProxy = new ServerProxy("failover1:2712")
            {
                AlternateServerProxy = new ServerProxy("failover2:2712")
            }
        };
    }
}

В этом примере подключается цепочка из 3 серверов (mainserver, failover1, failover2).

При вызове FetchData() всегда будет пытаться перейти на mainserver.

В случае неудачи он попытается failover1, а затем failover2, прежде чем, наконец, сгенерировать исключение.

Если бы это зависело от меня, я бы не стал использоватьчто-то быстрое и грязное, такое как:

public class FailoverServerProxy: IServer
{
    private readonly List<ServerProxy> _servers;
    public FailoverServerProxy RegisterServer(Server server)
    {
        _servers.Add(server);
        return this;
    }

    // Implement interface
    public object FetchData(object param)
    {
        foreach(var server in _servers)
        {
            try
            {
                return server.FetchData(param);
            }
            catch
            {
                // Failed. Continue to next server in list
                continue;
            }
        }

        // No more servers to try. No longer able to recover
        throw new Exception("Unable to fetch data");
    }    
}

public class Client
{
    private IServer _serverProxy;
    public Client()
    {
        // Wire up main server, and its failover/retry servers
        _serverProxy = new FailoverServerProxy()
                            .RegisterServer("mainserver:2712")
                            .RegisterServer("failover1:2712")
                            .RegisterServer("failover2:2712");        
    }

}

Я думаю, что оно заимствует идеи из других шаблонов, таких как Фасад, Стратегия и Прокси.

Но мои мотивы просто:

  1. Наименьшее влияние на существующие классы (т. Е. Отсутствие дополнительных свойств в классе Server)
  2. Разделение задач:
    • Центральный класс для логики отработки отказа / восстановления сервера.
    • Сохраните реализацию аварийного переключения / восстановления скрытой от клиента / сервера.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...