Хобрук: Ваш путь к мастерству в программировании

Утечка памяти в WCF (дуплекс) на сервере

Привет, у меня возникла проблема со службой, работающей с WCF в дуплексном режиме. Он пропускает память (не много, но около 80 МБ в день), и после того, как профилировщик памяти работал вместе со службой в течение 24 часов, я обнаружил, что большая часть памяти находится в byte[], на которую ссылается довольно беспорядок, но большинство ссылок заканчиваются примерно так : один путь, содержащий байт[] - массиви "корень" выглядит так: root

Я тоже вижу много ServiceChannel (около 200) поступающих (я думаю) из каналов обратного вызова.

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

В целом моя проблема кажется почти такой же, как эта: утечка памяти в реализации Silverlight Wcf но на стороне сервера.

Я даже пробовал упомянутую здесь вещь [MTAThread]: WCF служба пропускает дескрипторы и память, когда время ожидания клиента истекает, но это не решает проблему.

Я просто не думаю, что проблема связана с моим кодом, так как я оборачиваю каналы обратного вызова после его получения с помощью OperationContext.Current.GetCallbackChannel<IServiceConnectorCallback>() в один из моих собственных объектов, и они не протекают (есть только один из них для каждого клиента в памяти на любой моментальный снимок) - конечно, я несколько раз сбрасывал эти обратные вызовы, так как канал может измениться (клиенты теряют соединение или переподключаются), но у меня нет способа избавиться от старых ссылок, поэтому я только отбрасываю их, и GC должен сделать это работа на них.

Я использую PerCall в своем сервисе, поэтому у меня вообще нет дескриптора этих объектов в моем коде.

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

Поэтому, пожалуйста, дайте мне некоторую помощь/подсказки по этому поводу - большое спасибо!

21.02.2012

  • Видите ли вы более высокий прирост памяти, если клиенты часто ошибаются, и вам приходится заново создавать канал обратного вызова? Вы Abort используете канал обратного вызова, если клиент ушел? 21.02.2012
  • Мне трудно сказать, но это может быть так - и нет, я не прерываю канал на сервере (как я могу это сделать - используя GetCallbackChannel<T>, я получаю только T - вам нужно передать это через какой-то прокси ?) 21.02.2012
  • Вы должны быть в состоянии передать его на IClientChannel 21.02.2012
  • спасибо - нашел это в другом посте и реализую это прямо сейчас. Если я вас правильно понял, я должен вызвать .Abort на клиентском канале, если возникнет Faulted-Event, верно? - Я думаю, что могу даже улучшить свой код, обрабатывая .Close, поэтому у меня больше не будет проблем с публикацией отключенному клиенту. 21.02.2012
  • я тестирую это прямо сейчас - я думаю, что мне нужно подождать несколько часов, чтобы увидеть, все ли в порядке - Кстати: я должен вызывать dispose для закрытого / неисправного IClientChanels? 21.02.2012
  • что я уже могу сказать, так это то, что существует много ошибочных каналов обратного вызова - я думаю, это связано с тем, что клиенты перемещаются и немного меняют точки доступа. 21.02.2012
  • Я использую NetTcpBinding для этого 21.02.2012
  • К сожалению, похоже, что это не решает проблему - может быть, мне следует попытаться удалить клиентские каналы? 21.02.2012
  • Dispose на канале просто вызывает Close — вам все равно нужно прервать канал с ошибкой. Вы сохраняете клиентский канал и каждый раз извлекаете его из OperationContext? если это так, вы должны Close его, когда закончите с ним после каждого использования 21.02.2012
  • да, я узнал на собственном горьком опыте, что Dispose не является хорошей идеей, и да, я извлекаю/устанавливаю канал при каждом вызове, который я получаю от каждого клиента, поэтому я могу обновлять их по запросу. Но, насколько я могу судить, канал будет одним и тем же при каждом звонке, поэтому я заменяю их, только если это не так - я не закрываю канал в этом случае прямо сейчас, так как старый канал все равно должен был быть поврежден/закрыт, но я думаю, я мог бы попытаться добавить защищенный (только для State = Opened) вызов, чтобы закрыть там, если вы думаете, что это правильный путь 21.02.2012
  • @Richard: пожалуйста, оставьте свой комментарий в форме ответа - похоже, это решает проблему (прервать каждый клиентский канал, если зарегистрирован новый) или, по крайней мере, большую часть - большое спасибо! 24.02.2012
  • @CarstenKönig, какой анализатор памяти вы используете? 22.10.2014
  • @StephaneRolland Они мне не нужны очень часто, но я купил лицензию на ANTS MemoryProfiler у RedGate, но в большинстве случаев я смотрел назад, чем на пробную версию, и я бы порекомендовал попробовать их и решить для себя. 22.10.2014

Ответы:


1

Когда канал на основе сеанса дает сбой, вызов Close вызовет исключение. Однако есть ресурсы прокси-сервера, которые не очищаются в этом случае, и они очищаются только тогда, когда вы Abort выдаете неисправный канал.

Убедитесь, что при замене неисправного канала вы сначала Abort используете старый канал.

24.02.2012
Новые материалы

Деревья классификации и регрессии
Это мой второй пост об алгоритмах машинного обучения. Мой первый пост посвящен искусственным нейронным сетям, вы можете найти его ниже. Нейронные сети — базовое..

HMTL - Многозадачное обучение для решения задач НЛП
Достижение результатов SOTA путем передачи знаний между задачами Область обработки естественного языка включает в себя десятки задач, среди которых машинный перевод, распознавание именованных..

Решения DBA Metrix
DBA Metrix Solutions предоставляет удаленного администратора базы данных (DBA), который несет ответственность за внедрение, обслуживание, настройку, восстановление базы данных, а также другие..

Начало работы с Блум
Обзор и Codelab для генерации текста с помощью Bloom Оглавление Что такое Блум? Некоторые предостережения Настройка среды Скачивание предварительно обученного токенизатора и модели..

Создание кнопочного меню с использованием HTML, CSS и JavaScript
Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

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

Классы в JavaScript
class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..