建议实现故障转移机制的设计模式

时间:2012-02-24 18:47:59

标签: c# design-patterns

我有一个应用程序(比如App1)通过.net远程连接到另一个应用程序(App2)。 App2充当服务器..如果App2发生故障,App1将无法从App2中提取数据。我们计划在另一台机器上运行App2的实例(比如App2a),这样如果App2关闭,App1会自动从App2a获取数据。当App2再次运行时... App1将需要从App2获取数据。故障转移机制尚未实现...请建议设计模式,以便将来可以为App1添加任意数量的服务器实例来提取数据。

由于

1 个答案:

答案 0 :(得分:1)

我能想到的最接近的设计模式是责任链模式。

这个想法是:

  1. 构建一系列对象(服务器)
  2. 让对象(服务器)处理请求
  3. 如果无法执行此操作,请将请求传递给链
  4. 代码:

    // 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");        
        }
    
    }
    

    我认为它借鉴了Facade,Strategy和Proxy等其他模式的想法。

    但我的动机只是:

    1. 对现有类产生的影响最小(即Server类中没有额外属性)
    2. 关注点分离:
      • 服务器故障转移/恢复逻辑的中央类。
      • 保持故障转移/恢复的实现对客户端/服务器隐藏。