как реализовать распределенную систему для платформы мониторинга - PullRequest
3 голосов
/ 25 марта 2012

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

Проект основан на платформе Genesys Computer Telephony Integration (CTI) . По сути, используя SDK, предоставляемый Genesys, один клиент подписывается на несколько служб Genesys (или TServers ), работающих удаленно. Затем клиент регистрирует целую кучу номеров каталогов (DN), связанных с конкретным TServer , и ожидает события вызова. Когда происходит событие, оно захватывается клиентом и сохраняется в базе данных. Выполняется ряд других операций, что на данном этапе не имеет значения. Большая часть коммуникационной работы выполняется объектом 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 и целый ряд других «объектов». Это действительно просто модная СУБД. Разница в том, что вы также можете подписаться на сервер конфигурации и зарегистрироваться для событий CRUD (например, CreateEvent , UpdateEvent и т. Д.). Не иллюстрируя код, концепция аналогична приведенной выше. (т.е. вы можете зарегистрироваться на нескольких разных серверах конфигурации и прослушивать события CRUD).

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

Я пытаюсь реализовать распределенную систему. В двух словах, система будет состоять из 2 компонентов. Компоненты служб мониторинга и службы диспетчера (все они будут службами Windows)

Компонент службы мониторинга

  • «Службы мониторинга» подключаются к одному или нескольким T-серверам для отслеживания событий вызовов
  • Служба мониторинга ТАКЖЕ подпишется на диспетчерскую службу

Компонент диспетчерского обслуживания

  • «Диспетчерская служба» подключается к одному или нескольким серверам конфигурации и ожидает событий CRUD.
  • Как только происходит событие (то есть на сервере конфигурации было добавлено новое DN), диспетчер захватывает событие создания и уведомляет всех подписчиков службы мониторинга. Впоследствии диспетчер также обновит локальную базу данных, поэтому информация о DN сохраняется для избыточности (в случае, если диспетчер не может подключиться к серверу конфигурации).
  • Подписчик мониторинга, которому принадлежит вновь созданный DN (отличающийся уникальными идентификаторами DBID и TServerID), примет DN и зарегистрирует его для прослушивания событий (аналогично показанному в первом фрагменте кода). Абонент мониторинга, который не обладает требуемым соединением TServer, естественно, отклонит полученный запрос.
  • Диспетчер также может получать вновь добавленные TS-серверы, но на этот раз он примет решение, какую службу мониторинга он хочет использовать, чтобы эта служба мониторинга установила ДРУГОЕ соединение. Это будет определяться такими факторами, как количество текущих сеансов, запущенных в службе мониторинга, или объем памяти, который проверяет один сервис в данный момент.

Я выдвинул некоторые базовые концепции, и вот код, иллюстрирующий то, что я сделал до сих пор:

Метод связи, который я выбрал - WCF с NetTcpBinding , поэтому для простоты я открыл интерфейс:

[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. Как мне обращаться с классом DisMonService при попытке передать сообщения всем подписчикам изДиспетчерская служба.т. е. было добавлено новое DN, давайте вызовем класс DisMonService и уведомим всех подписчиков.
  2. Какой самый оптимальный шаблон для применения при обновлении всех подписчиков из DisMonServie

В данный момент мой фиктивный клиент подключается к диспетчеру и регистрируется самостоятельно.В дальнейшем, как лучше всего получить доступ к классу DisMonService .

Надеюсь, я никого не смущаю в том, что пытаюсь спросить.Я думаю, что я действительно пытаюсь найти, это лучший способ реализовать вышеуказанную систему, любые предложения и тому подобное.Некоторые примеры кода и фрагменты кода были бы действительно полезны.

Это мой первый пост здесь, поэтому я приношу извинения всем, если я не объяснил себя стандартам форума.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...