Как работает экземпляр WCF

Я пытаюсь понять, как работают экземпляры с WCF. У меня есть служба WCF, для которой InstanceContextMode установлен на PerCall (поэтому для каждого вызова каждого клиента будет создаваться новый экземпляр), а для ConcurrencyMode установлено значение Single (таким образом, экземпляр службы выполняет ровно один вызов операции или вообще не выполняет ее).

Итак, я понимаю, что при подключении клиента создается новый экземпляр. Но что происходит, когда клиент покидает сервис. Экземпляр умирает. Я спрашиваю, потому что мне нужно реализовать ConcurrentQueue в сервисе. Таким образом, клиент подключится к сервису и загрузит данные для обработки, а затем покинет сервис. Рабочие будут работать из очереди. После того, как работа закончена, мне нужно уничтожить экземпляр.

2 ответа

Решение

По сути, изучая мастер-класс WCF, которым руководствовался Юваль Лоуи, активация по вызову является предпочтительным выбором для служб, которые необходимо масштабировать, то есть обрабатывать множество одновременных запросов.

Зачем?

При каждом вызове каждый входящий запрос (до настраиваемого предела) получает собственный, свежий, изолированный экземпляр класса обслуживания для обработки запроса. Создание класса обслуживания (простой старый класс.NET) не требует больших затрат - и среда выполнения WCF может легко управлять 10, 20, 50 одновременно работающими экземплярами службы (если ваше серверное оборудование может справиться с этим). Так как каждый запрос получает свой собственный экземпляр сервиса, этот экземпляр обрабатывает только один поток за раз - и это абсолютно легко программировать и обслуживать, никаких суетливых блокировок и прочего, необходимых для обеспечения его потоковой безопасности.

Использование единого сервиса (InstanceContextMode=Single) либо ужасное узкое место (если у вас есть ConcurrencyMode=Single - затем каждый запрос сериализуется, обрабатывается один за другим), или если вы хотите достойного выполнения, вам нужно ConcurrencyMode=Multiple, но это означает, что у вас есть один экземпляр вашего класса обслуживания, обрабатывающий несколько параллельных потоков - и в этом случае вы как программист этого класса обслуживания должны быть на 100% уверены, что весь ваш код, весь ваш доступ к переменным и т. д. равен 100% Потокобезопасный - и это действительно задача! Лишь очень немногие программисты действительно овладевают этим черным искусством.

По моему мнению, затраты на создание экземпляров классов обслуживания в сценарии для каждого вызова ничто по сравнению с требованиями создания полностью поточно-ориентированной реализации для многопоточного одноэлементного класса обслуживания WCF.

Так что в вашем конкретном примере с центральной очередью я бы:

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

  • создать рабочую службу (службу Windows NT или что-то в этом роде), которая затем читает очередь и выполняет обработку - это в основном полностью независимо от любого кода WCF - это просто выполнение удаления из очереди и обработки

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

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

Я бы порекомендовал вам использовать IntanceContextMode=Single и ConcurrencyMode для Mutli с резьбой. Это лучше масштабируется. Если вы используете эту схему, у вас будет одна параллельная очередь, и вы можете хранить все свои элементы в этой очереди.

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

Другие вопросы по тегам