Служба WCF Внутренний пожар / Забыть очередь - PullRequest
1 голос
/ 19 августа 2011

В настоящее время я внедряю сервис, использующий WCF, который управляет операциями с базой данных CRM.Я реализовал несколько аспектов CQRS, чтобы разделить все операции на отдельные команды и запросы.

Вопрос 1:

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

Я думал о том, чтобы разделить их на второй сервис WCF с односторонними операциями.Таким образом, исходная операция может немедленно вернуться, а служба «Триггер» может обрабатывать все эти вторичные операции.В настоящее время надежность не является серьезной проблемой, поэтому журналирование проблем будет достаточно, но может быть расширено в будущем.

Является ли это типичным способом обработки такого сценария?Или есть способ, которым это может быть выполнено без использования вторичной службы?

Вопрос 2:

Существуют ли существенные улучшения производительности от разделения служб WCF, подобных этой, на одном сервере?

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

Ответы [ 3 ]

1 голос
/ 24 августа 2011

Я согласен с Алексеем, что очередь может быть лучшим вариантом, чем служба WCF, если вы хотите масштабироваться.Это также позволит вам перемещать ваши команды в одностороннем порядке и действительно просто вернуть пользователю базовое подтверждение того, что команда была получена и обрабатывается (а не обрабатывается).

IПредлагаю вам ознакомиться с введением Грега Янга в документ CQRS на его CQRS Info сайте, в частности в разделе «Командная сторона» (примерно на полпути вниз).

Ответы на ваши вопросы:

  1. Перейдя в очередь или службу WCF, которая является односторонней, я думаю, что это решит вашу проблему.Ваша односторонняя служба получает команду от клиента, а затем передает ее в ваш домен для обработки.Ваш домен будет затем запускать 0, 1 или много событий в зависимости от того, что нужно сделать - эти события могут быть вызовами других служб WCF в вашем приложении или сообщениями, отброшенными в очередь, полученную вашим обработчиком событий.Ключ в том, что вы позволяете бизнес-правилам (доменам) определять, какие события вызывать.Как они обрабатываются конкретно - это деталь реализации (но я бы выбрал очередь или хранилище событий).Проверьте Магазин событий Джонатана Оливера .
  2. Я думаю, что чем быстрее вы можете освободить потоки IIS (или потоки в целом), это хорошая вещь;так что если вы поделите свои услуги на синхронные и асинхронные, это может быть хорошо.Я думаю, что если вы идете по пути CQRS, то одностороннее использование ваших служб для простого возврата сообщений ack / nack, вероятно, является хорошей вещью и может помочь вам с точки зрения производительности, поскольку вы, вероятно, быстрее освободите потоки для обработки большегозапросы.

Надеюсь, это поможет.Удачи !!

1 голос
/ 21 мая 2012

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

Вы упомянули, что вы разделили свои «триггеры».Я предполагаю, что это означает, что они запускаются как отдельные методы?В таком случае вы можете легко запустить их в фоновом режиме и позволить вашему основному потоку WCF вернуться без необходимости разделения служб.(Приведенный ниже код НЕ предполагает получение событий.)

public class MyCommandHandler
{
    public string Do(MyCommand1 command)
    {
        var myCrmObject = ... ; // load some object
        string message = myCrmObject.CriticalWork(command); // synchronous
        ThreadPool.QueueUserWorkItem(x => myCrmObject.OtherWork(command)); // async
        // async alternative 1
        //Action<MyCommand1> action = myCrmObject.OtherWork; // make into action delegate
        //action.BeginInvoke(null, command); // start action async, no callback
        // async alternative 1a - custom delegate instead of Action. same BeginInvoke call
        // async alternative 2 - Background Worker
        // async alternative 3 - new System.Threading.Thread(...).Start(command);
        return message; // will be here before OtherWork finishes (or maybe even starts)
    }
}

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

0 голосов
/ 19 августа 2011

Просто предложение

  1. Можно попробовать рабочую очередь, некоторые службы на внешнем интерфейсе асинхронно добавляют элементы. Другие сервисы на бэк-энде снимают предметы и обрабатывают работу. Состояние работы сохраняется в постоянном хранилище, где его можно запросить.

  2. Лучше иметь несколько рабочих по обе стороны очереди, но для любых улучшений ваш сервер должен быть многоядерным (многопроцессорным), поэтому он сможет по-настоящему распараллеливать работу. Возможно, вам придется попробовать разные варианты и посмотреть, что лучше.

...