2013-05-31 5 views
12

У нас есть консольное приложение C# (.Net 4.0), которое «самостоятельно» использует две службы WCF: один использует WSHttpBinding, а другой использует BasicHttpBinding.Приложение WCF «Self-Hosted» перестает отвечать на запросы

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

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

Проблема заключается в том, что с перерывами приложение обслуживания перестает отвечать на запросы. Хотя сам сервер продолжает работать (он продолжает записывать в файл журнала), все действия WCF (на обоих ServiceHost с), похоже, «захватывают». Новые запросы не обрабатываются (хотя TCP-соединения принимаются). Кроме того, количество потоков, потребляемых приложением, начинает резко увеличиваться со скоростью около одного нового потока в секунду. Сам код ничего не делает с Thread s или 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 here enter image description here

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

+1

Как вы в .net4, вы можете взять дамп своего процесса с помощью задачи mgr и перетащить этот файл дампа обратно в VS и посмотреть на параллельные стеки, чтобы увидеть, что происходит. * hopefully * его очевидно, иначе вам, возможно, придется идти по маршруту windbg. (используя тот же файл дампа). Надеюсь, проблема раскрывается как нечто простое, как что-то неподобающее, которое посылают ваши клиенты, которые непреднамеренно поддерживают вашу очередь обработки. – wal

+1

Закрываете ли вы своих клиентов после вызова метода? Может быть связано http://johan.driessen.se/posts/do-not-forget-to-close-your-wcf-serviceclients – keyboardP

+1

Я полагаю, вы пробовали, но ... вы включили сбор (почти) ВСЕ ** счетчики производительности **, связанные с вашим процессом? Когда это произойдет, вы можете сравнить собранные данные (_contention_ растет вместе с потоками? Использование памяти растет быстрее, чем потоки?) И так далее ...) –

ответ

2

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

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

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

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

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

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

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

2

Что такое параллельный режим для службы? и instancecontextmode?

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

2

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

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. 
0

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

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

Смежные вопросы