У меня возникли проблемы с реализацией правильных шаблонов для рабочего проекта, и я не хочу предшествовать, пока не буду удовлетворен правильной стратегией проектирования.
Проект основан на платформе 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;
}
}
Из приведенного выше кода очевидно, что каждая подписывающаяся служба мониторинга имеет уникальный идентификатор, что позволяет получить правильный контекст обратного вызова службы (на случай, если я решу сделать какие-нибудь другие веселые операции).
Именно здесь по сути и начинается моя дилемма.Короче говоря, мои вопросы следующие:
- Как мне обращаться с классом DisMonService при попытке передать сообщения всем подписчикам изДиспетчерская служба.т. е. было добавлено новое DN, давайте вызовем класс DisMonService и уведомим всех подписчиков.
- Какой самый оптимальный шаблон для применения при обновлении всех подписчиков из DisMonServie
В данный момент мой фиктивный клиент подключается к диспетчеру и регистрируется самостоятельно.В дальнейшем, как лучше всего получить доступ к классу DisMonService .
Надеюсь, я никого не смущаю в том, что пытаюсь спросить.Я думаю, что я действительно пытаюсь найти, это лучший способ реализовать вышеуказанную систему, любые предложения и тому подобное.Некоторые примеры кода и фрагменты кода были бы действительно полезны.
Это мой первый пост здесь, поэтому я приношу извинения всем, если я не объяснил себя стандартам форума.