如何为监控平台实现分布式系统

时间:2012-03-25 00:43:52

标签: c# design-patterns distributed-system

我在为工作项目实施正确的模式时遇到一些麻烦,我不想在我对正确的设计策略感到满意之前先行。

该项目基于 Genesys计算机电话集成(CTI)平台。基本上,利用Genesys提供的SDK,单个客户端订阅远程运行的许多Genesys服务(或 TServers )。然后,客户端注册与特定 TServer 相关联的整堆目录号码(DN&#),并等待呼叫事件。当事件发生时,它将被客户端捕获并存储在数据库中。执行了许多其他操作,这在此阶段是无关紧要的。许多通信工作由Genesys ProtocolManager 对象处理,因此单个事件处理程序捕获所有客户端的事件数据,而后者又由 EventBrokerService 处理。这是一个简单的代码,用于说明连接过程,单个DN的注册和事件功能:

        EventBrokerService eventBrokerService;

        using (var client = new TServerProtocol(
            new Endpoint(
                new Uri("tcp://tserver01:11234"))))
        {
            client.Open();

            eventBrokerService = BrokerServiceFactory.CreateEventBroker(client);
            eventBrokerService.Activate();
            eventBrokerService.Register(this.OnEvent);

            RequestRegisterAddress requestRegisterAddress = 
                    RequestRegisterAddress.Create("977845873", 
                                                  RegisterMode.ModeMonitor, 
                                                  ControlMode.RegisterDefault, 
                                                  AddressType.DN);
            IMessage response = client.Request(requestRegisterAddress);
        }

然后我们会听事件(有很多不同的事件):

    private void OnEvent(IMessage response)
    {
        switch (response.Id)
        {
            case EventACK.MessageId:
                //do something
                break;
            case EventLinkConnected.MessageId:
                var ev = response as EventLinkConnected;
                //Insert event into DB and perform some other operations...
                break;
        }
    }

Genesys平台附带另一个称为Genesys配置服务器的组件。配置服务器保存所有TServer详细信息,包括DN信息和一大堆其他"对象"。它真的只是一个奇特的DBMS。不同的是,您还可以订阅配置服务器并注册CRUD事件(即 CreateEvent UpdateEvent 等...)。没有说明代码,概念类似于上面的概念。 (即您可以注册到许多不同的配置服务器并监听CRUD事件。)

在大多数情况下,我已经涵盖了上述内容,我对目前的实施感到满意。我想要实现的目标如下:

我正在尝试实现分布式系统。简而言之,该系统将包含2个组件。监控服务和调度程序服务组件(它们都将是Windows服务)

监控服务组件

  • "监控服务"连接到1个或多个T服务器以监控呼叫事件
  • 监控服务将 订阅调度程序服务

调度程序服务组件

  • " Dispatcher Service"连接到一个或多个配置服务器并等待CRUD事件。
  • 一旦发生事件(即在配置服务器上添加了新DN),调度程序将捕获创建事件,并通知所有监视服务订户。随后,调度程序还将更新本地数据库,因此将保留DN信息以实现冗余(如果调度程序无法连接到配置服务器)。
  • 新创建的DN所属的监控订户(由唯一的DBID和TServerID标识符区分)将接受DN,并将其注册用于监听事件(类似于第一个代码段中所示)。不具备所需TServer连接的监控用户自然会丢弃收到的请求。
  • Dispatcher也可以接收新添加的TServers,但这一次,它将决定它想要使用哪个监控服务,以便该监控服务进行另一个连接。这将取决于多种因素,例如监控服务上运行的当前会话数或当时单个服务正在咀嚼的内存量。

我已经提出了一些基本概念,这里有一些代码来说明我到目前为止所做的工作:

我选择的通信方法是带有 NetTcpBinding 的WCF,所以对于简单的部分,我公开了一个接口:

[ServiceContract(Namespace = "urn:Netwatch", 
                 SessionMode = SessionMode.Required, 
                 CallbackContract = typeof(IDisMonServiceCallback))]
public interface IDisMonService
{
    [OperationContract]
    bool Subscribe(string uid);
    [OperationContract(IsOneWay = true)]
    void Unsubscribe(string uid);
}

[ServiceContract(Namespace="urn:Netwatch")]
public interface IDisMonServiceCallback
{
    [OperationContract]
    bool DNRegistered(int tServerId, string dnEntry);
}

在调度员身上,我实施了它:

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class DisMonService : IDisMonService
{
    private ConcurrentDictionary<string, IDisMonServiceCallback> subscribers = new ConcurrentDictionary<string, IDisMonServiceCallback>();

    public IDisMonServiceCallback this[string uid]
    {
        get
        {
            IDisMonServiceCallback callback;
            if (!subscribers.TryGetValue(uid, out callback))
                return null;
            return callback;
        }
    }

    public List<IDisMonServiceCallback> GetAllServiceCallbacks()
    {
        return new List<IDisMonServiceCallback>(subscribers.Values);
    }

    public bool Subscribe(string uid)
    {
        IDisMonServiceCallback callback = GlobalHelper.Callback<IDisMonServiceCallback>();

        if (!subscribers.ContainsKey(uid))
            if (!subscribers.TryAdd(uid, callback))
                return false;
        return true;
    }

    public void Unsubscribe(string uid)
    {
        IDisMonServiceCallback callback;

        if (subscribers.ContainsKey(uid))
            if (!subscribers.TryRemove(uid, out callback))
                return;
        return;
    }
}

从上面的代码可以看出,每个订阅监控服务都有一个唯一的标识符,这样就可以检索到正确的服务回调上下文(如果我决定做其他一些时髦的操作)。

这就是我的困境基本上开始的地方。长话短说,我的问题如下:

  1. 在尝试从Dispatcher服务中向所有订阅者传递消息时,如何处理 DisMonService 类。即已添加新DN,让我们调用 DisMonService 类并通知所有订阅者。
  2. DisMonServie
  3. 中处理所有订阅者更新时实施的最佳模式是什么?

    目前我的虚拟客户端连接到调度程序,它自己注册。接下来,访问 DisMonService 类的最佳方式是什么。

    我希望我不会因为我想要问的问题而混淆任何人。我想我真正想要找到的是实现上述系统的最佳方式,任何建议等。一些代码示例和代码段确实会有所帮助。

    这是我在这里的第一篇文章,所以如果我没有向论坛的标准解释,我向任何人道歉。

0 个答案:

没有答案