Приложение WCF "Self-Hosted" становится невосприимчивым

У нас есть консольное приложение С# (.Net 4.0), в котором "self hosts" используются две службы WCF: один используется WSHttpBinding, а другой использует BasicHttpBinding.

Подключаясь к этим сервисам, у нас есть два отдельных клиентских приложения: служба на основе Silverlight, которая использует BasicHttpBinding, и другое консольное приложение, использующее WSHttpBinding.

У приложения службы WCF обычно около 30 пользователей, подключенных через клиент Silverlight, и еще пару подключений от клиента консольного приложения. Он не "плоский" каким-либо образом; каждый клиент запрашивает службу WCF, возможно, один раз каждые 5 секунд.

Проблема заключается в том, что с перерывами приложение-служба перестает отвечать на запросы. Хотя сам сервер продолжает работать (он продолжает записывать в файл журнала), все действия WCF (на обоих ServiceHost s) выглядят как "захватить". Новые запросы не обрабатываются (хотя TCP-соединения принимаются). Кроме того, количество потоков, потребляемых приложением, начинает резко увеличиваться со скоростью около одного нового потока в секунду. Сам код ничего не делает с Thread или ThreadPool s, хотя иногда он выдает Thread.Sleep на несколько сотен миллисекунд.

К сожалению, проблема заключается в прерывистом характере проблемы: код регулярно работает в течение нескольких часов, даже дней без каких-либо проблем. Затем, без видимых причин, он внезапно перестает отвечать на запросы, и количество потоков начинает тикать.

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

На всякий случай проблема была в WCF Throttling, я добавил этот код:

 ServiceThrottlingBehavior throttlingBehavior = new System.ServiceModel.Description.ServiceThrottlingBehavior
                                                           {
                                                               MaxConcurrentCalls = 512,
                                                               MaxConcurrentInstances = 8192,
                                                               MaxConcurrentSessions = 8192
                                                           };

        host.Description.Behaviors.Add(throttlingBehavior);
        host2.Description.Behaviors.Add(throttlingBehavior);

.. без видимого эффекта.

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

Означает ли поведение, описанное выше, знакомое кому-либо, или может ли кто-нибудь предложить наилучший способ устранения этой проблемы?

EDIT: следуя рекомендациям Wal ниже, я захватил .DMP приложения, когда он начал ошибочно вести себя, и глядя на представление параллельных стеков в VS2012, я вижу:

enter image description hereenter image description here

... и другие очень похожи, но с различным количеством потоков. Я недостаточно умен, чтобы декодировать именно то, что это значит. Может ли кто-нибудь предложить, где начать смотреть дальше?

Ответ 1

Спасибо всем, кто прокомментировал и ответил; ваши предложения и вклад действительно помогли - не в последнюю очередь, подтвердить, что это не похоже на что-то тривиальное, что я пропустил.

Однако, и немного разочаровывает, проблема, похоже, исчезла. Вот что я изменил:

  • Приложение регулярно записывалось на консоль (мой метод "WriteToLog" имел Console.WriteLine, а также добавлял к файлу, это было исключительно для моего удобства во время разработки). Приложение также запускалось как служба с использованием FireDaemon, и по какой-то причине мы начали видеть высокое время процессора на conhost.exe. Чтобы противодействовать этому, я прокомментировал Console.WriteLine.

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

В результате приложение стало намного "тише" с точки зрения использования ЦП. Как отмечали другие, в коде есть почти наверняка "состояние гонки", но, делая более эффективную базовую машину и код более эффективным, кажется, что я уменьшил шансы на состояние гонки. Конечно, проблема, которая возникала хотя бы раз в день, не происходила почти через неделю.

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

Еще раз спасибо за помощь, и здесь, надеясь, что код не упадет сразу после нажатия кнопки Post Your Answer:/

Ответ 2

каков режим параллелизма для службы? и instancecontextmode?

defaultcontextmode по умолчанию для сеанса, возможно, стоит изменить это на percall, это будет использовать больше памяти, но будет гарантировать, что каждый экземпляр службы не висит вокруг (при условии, что клиент правильно удален из http://coding.abel.nu/2012/02/using-and-disposing-of-wcf-clients/)

Ответ 3

Как указывалось раньше, звучит так, будто у вас есть состояние гонки. Не можете ли вы случайно проверить System.ServiceModel.ICommunicationObject.State соединения где-нибудь в коде? См. статья MSDN:

Checking the value of the System.ServiceModel.ICommunicationObject.State property is 
a race condition and is not recommended to determine whether to reuse or close a channel.

Ответ 4

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

С другой стороны, это может быть WCF, получили ли вы много ударов по вашей службе WCF? Попробуйте разобрать его. http://msdn.microsoft.com/en-us/library/system.servicemodel.description.servicethrottlingbehavior.maxconcurrentinstances.aspx