Служба WCF для многих одновременных клиентов и доступа к базе данных

Я новичок в сервисах WCF и задаюсь вопросом, каким будет лучший способ решить следующее.

У меня есть много клиентов (~ 200 - ~ 500), которые все время делают запросы моего обслуживания довольно постоянно в течение рабочего дня. Большинство запросов включают опрос базовой базы данных для подачи правильного ответа.

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

Было бы лучше ограничить количество одновременных подключений к службе WCF и, следовательно, непреднамеренно уменьшить возможное количество подключений к базе данных?

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

Большое спасибо за любой совет.

Ответ 1

Как уже упоминал Маркос - WCF имеет встроенную функцию дросселирования, которую вы можете настроить на сервере. Это предотвратит, что ваш сервер базы данных будет заполнен слишком большим количеством запросов одновременно.

По умолчанию:

<serviceThrottling 
      maxConcurrentCalls="16"
      maxConcurrentSessions="10" 
      maxConcurrentInstances="26" />

Подробнее см. документы MSDN на ServiceThrottlingBehavior.

Это означает, что максимум 16 вызовов обрабатываются одновременно WCF, то есть IF ваш класс службы WCF позволяет сразу несколько вызывающих абонентов!

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

Если вы сделаете свой класс обслуживания WCF одиночным, вам нужно либо установить его ConcurrencyMode в Multiple - но тогда вам нужно проявлять особую осторожность, чтобы не позволить двум одновременным потокам в вашем классе изменять одни и те же значения друг под другом; многопоточное безопасное программирование - главная задача! Или вы не устанавливаете режим concurrency в Multiple, но тогда ваш единственный и единственный экземпляр класса WCF может обрабатывать запросы только последовательным образом, по одному - не очень масштабируемым!

Первой вызов и один экземпляр службы для каждого запроса, безусловно, намного проще. Это с дросселированием сервисов на месте и с пулом соединений ADO.NET создает очень мощную и хорошо себя зарекомендовавшую среду!

Также см. Дэн Ригсби превосходный пост в блоге по регулированию обслуживания WCF для более подробной информации.

Ответ 2

Если вы используете ADO для подключения к своей базе данных, он должен обеспечить механизм объединения пулов, поэтому вам не нужно иметь дело с этим.

Пожалуйста, прочитайте эту статью для получения дополнительной информации: Объединение пулов ADO.NET с первого взгляда

Ответ 3

У нас есть аналогичный сценарий, и мы решаем его, используя только один коннект из нашего WebService в БД и используя MARS из SqlServer, который работает отлично и довольно быстро. Sql Server действительно знает, как обрабатывать параллельные запросы, о которых вы не должны думать.

Вы избегаете того, что накладные расходы на открытие и закрытие соединений (очевидно, что объединение пулов в этом случае помогает)

Помните также добавить в свой веб-сервис что-то вроде:

  [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
        ConcurrencyMode = ConcurrencyMode.Multiple)]

И в config:

<serviceThrottling maxConcurrentCalls="100"
 maxConcurrentSessions="100" 
 maxConcurrentInstances="100" />

Эта опция находится внутри

  <behaviors>
      <serviceBehaviors>
        <behavior name="...">

Надеюсь, что это поможет:)