Сведения о вопросе

FUTER

19:36, 25th August, 2020

Теги

Windows Увеличение Объема Услуг CPU Потребление

Просмотров: 424   Ответов: 7

На моей работе у меня есть сцепление из шести Windows services, за которое я отвечаю, написанное в C# 2003 году. Каждая из этих служб содержит таймер, который срабатывает каждую минуту или около того, где происходит большая часть их работы.

Моя проблема заключается в том, что по мере запуска этих служб они начинают потреблять все больше и больше времени CPU через каждую итерацию цикла, даже если для них нет никакой значимой работы (т. е. они просто бездельничают, просматривая базу данных для чего-то). Когда они запускаются, каждая служба использует в среднем (около) 2-3% из 4 CPUs, что нормально. Через 24 часа каждая служба будет потреблять весь процессор на протяжении всего цикла выполнения своего цикла.

Кто-нибудь может помочь? Я в недоумении, что может быть причиной этого. Наше текущее решение заключается в том, чтобы перезапускать сервисы один раз в день (они отключаются сами, затем скрипт видит, что они отключены, и перезапускает их примерно в 3 часа ночи). Но это не долгосрочное решение; меня беспокоит то, что, поскольку службы становятся более загруженными, перезапуска их один раз в день может быть недостаточно... но поскольку существует значительный штраф за запуск (все они используют NHibernate для доступа к данным), поскольку они становятся более загруженными, именно то, что мы не хотим делать, - это перезапускать их чаще.


@akmad: правда, это очень трудно.

  1. Да, служба, запущенная изолированно, будет показывать тот же симптом с течением времени.
  2. Нет, это не так, мы уже смотрели на это. Это может произойти в 10 утра, в 6 вечера или в середине ночи. Здесь нет никакой последовательности.
  3. Мы делаем это, а они делают. Службы делают именно то, что они должны делать, и ничего больше.
  4. К сожалению, это требует предвидения того, когда именно услуги будут исчерпаны CPUs, что происходит по непредсказуемому графику и никогда не бывает очень быстро... что делает вещи вдвойне трудными, потому что мой босс будет запускать и перезапускать их, когда у них начнутся проблемы, не думая о проблемах отладки.
  5. Нет, они используют довольно стабильное количество RAM (ок. 60-80MB каждый, из 4 ГБ на машине).

Хорошие предложения, но rest заверил, что мы перепробовали все обычные способы устранения неполадок. Я надеюсь, что это проблема .NET, о которой кто-то может знать, и мы сможем работать над ее решением. Решение моего босса (которое я категорически не хочу реализовывать) состоит в том, чтобы поместить поле в базу данных, которая содержит несколько раз для перезапуска служб в течение дня, чтобы он мог устранить проблему и не думать о ней. Я Отчаянно ищу причину реальной проблемы, чтобы исправить ее, потому что это решение станет катастрофой примерно через шесть месяцев.


Эллис: у каждого из них своя функция. Один читает записи из базы данных Oracle где-то за пределами объекта; другой обрабатывает эти записи и передает файлы, принадлежащие этим записям, в нашу систему; третий проверяет эти файлы, чтобы убедиться, что они такие, какими мы их ожидаем; другой-это Служба технического обслуживания, которая постоянно проверяет такие вещи, как дисковое пространство (которого у нас достаточно) и опрашивает другие серверы, чтобы убедиться, что они живы; один работает только для того, чтобы убедиться, что все эти другие работают и выполняют свою работу, отслеживает и сообщает об ошибках и перезапускает все, что не удалось сохранить всю систему это происходит 24 часа в сутки.

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


@Joshdan: никакого секрета. Как я уже сказал, мы испробовали все обычные способы устранения неполадок. Профилирование было бесполезным: профилировщик, который мы используем, не мог указать на какой-либо код, который фактически выполнялся, когда использование CPU было высоким. Эти службы были разорваны около месяца назад в поисках этой проблемы. Каждый раздел кода был проанализирован, чтобы попытаться выяснить, был ли наш код проблемой; я здесь не спрашиваю, потому что я не сделал свою домашнюю работу. Если бы это был простой случай, когда службы выполняли больше работы, чем ожидалось, это было бы поймано.

Проблема здесь заключается в том, что в большинстве случаев службы вообще ничего не делают, но все же умудряются потреблять 25% или более из четырех ядер CPU: они не находят никакой работы, выходят из своего цикла и ждут следующей итерации. Это должно, в буквальном смысле, почти не занимать времени CPU вообще.

Вот пример поведения, которое мы наблюдаем на службе без работы в течение двух дней (в неизменной среде). Это было захвачено на прошлой неделе:

День 1, 8 утра: авг. CPU использование приблизительно 3%
День 1, 6 вечера: авг. CPU использование приблизительно 8%
День 2, 7 утра: авг. CPU использование приблизительно 20%
День 2, 11 утра: авг. CPU использование приблизительно 30%

Рассмотрев все возможные мирские причины этого, я задал этот вопрос здесь, потому что я полагал (правильно, как оказалось), что получу более новаторские ответы (как Убигути) или указатели на вещи, о которых я не думал (как предложение Яна).


Так же происходит и Спайк CPU непосредственно перед таймером обратный вызов, в пределах обратного вызова таймера, или сразу после таймера обратный звонок?

Вы меня неправильно поняли. Это не Спайк. Если бы это было так, то не было бы никаких проблем; я могу справиться со спайками. Но это не так... использование CPU в целом растет. Даже когда служба ничего не делает, ожидая следующего удара таймера. Когда сервис запускается, все идет хорошо и спокойно, и график выглядит так, как вы и ожидали... как правило, использование 0%, с шипами до 10%, когда NHibernate попадает в базу данных или сервис выполняет какой-то тривиальный объем работы. Но это увеличивает до across-the-board 25% (больше, если я позволю ему зайти слишком далеко) использование во все времена, пока процесс запущен.

Это сделало предложение Йена логичной серебряной пулей (NHibernate делает много вещей, когда вы не смотрите). Увы, я реализовал его решение, но оно не возымело эффекта (у меня нет доказательств этого, но я действительно думаю, что это ухудшило ситуацию... среднее использование, кажется , теперь растет намного быстрее). Обратите внимание, что удаление NHibernate "sections" (как вы рекомендуете) нецелесообразно, так как это было бы уберите около 90% кода в сервисе, что позволило бы мне исключить таймер как проблему (которую я абсолютно намерен попробовать), но не может помочь мне исключить NHibernate как проблему, потому что если NHibernate вызывает это, то хитроумное исправление, которое реализовано (см. ниже), просто должно стать способом работы системы; мы настолько зависим от NHibernate для этого проекта, что PM просто не примет, что это вызывает неразрешимую структурную проблему.

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

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

Это чрезвычайно интригует (постольку как Вы доверяете своему профайлеру).

Я не. Но тогда это Windows services, написанные в .NET 1.1, запущенные на машине Windows 2000, развернутой хитрым сценарием Nant, использующим старую версию NHibernate для доступа к базе данных. На самом деле, я бы сказал, что мало чему доверяю на этой машине.



  Сведения об ответе

lats

13:11, 16th August, 2020

Вы упомянули, что используете NHibernate-закрываете ли вы свои NHibernate сеансы в соответствующие моменты (например, в конце каждой итерации?)

Если нет, то размер карты объектов, загруженной в память, будет постепенно увеличиваться с течением времени, и каждый сеанс Флеша будет занимать все больше времени CPU.


  Сведения об ответе

davran

11:01, 12th August, 2020

Вот с чего я бы начал:

  1. Получить процесс Explorer и показать %Time в JIT, %Time в GC, CPU циклов Дельта, CPU времени, CPU % и потоков.
  2. Вам также понадобится kernel и пользовательское время, а также несколько репрезентативных трассировок стека, но я думаю,что вам нужно нажать Свойства, чтобы получить снимки.
  3. Сравните до и после выстрелов.

Пара мыслей о возможностях:

  • чрезмерное GC (%времени в GC идет вверх. Кроме того, счетчики Perfmon GC и CPU будут соответствовать)
  • избыточные потоки и связанные с ними переключатели контекста (# потоков, идущих вверх)
  • опрос (трассировки стека последовательно перехватываются в одной функции)
  • чрезмерное kernel время (kernel раз являются высокими-Диспетчер задач показывает большие числа времени kernel, когда CPU является высоким)
  • исключения (кинули вкладке PE .NET исключения высок и становится все выше. Есть также счетчик производительности)
  • вирус/руткит (OK, это сценарий последней канавы - но можно построить руткит, который скрывается от TaskManager. Я подозреваю, что вы могли бы затем распределить свое неизбежное использование CPU на другой процесс, если бы Вы были достаточно хитры. Кроме того, если вы исключили все вышеперечисленное, у меня сейчас нет идей)


  Сведения об ответе

ASSembler

11:42, 16th August, 2020

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

  1. Что происходит, когда вы запускаете только одну из служб одновременно? Вы все еще видите замедление? Это может свидетельствовать о том, что между службами существуют определенные разногласия.
  2. Всегда ли проблема возникает примерно в одно и то же время, независимо от того, как долго работает служба? Это может указывать на то, что что-то другое (резервное копирование, проверка на вирусы и т. д.) вызывает замедление работы машины (или БД) в целом.
  3. Есть ли у вас логирование или какой-то другой механизм, чтобы быть уверенным, что служба выполняет работу только так часто, как вы считаете нужным?
  4. Если вы можете увидеть снижение производительности в течение короткого периода времени, попробуйте запустить службу на некоторое время, а затем прикрепите профилировщик, чтобы точно увидеть, что привязывает CPU.
  5. Вы ничего не говорите об использовании памяти. Есть ли у вас какая-либо информация об этих услугах? Вполне возможно, что вы используете большую часть RAM и вызываете на диске мусор или какую-то подобную проблему.

Желаю удачи!


  Сведения об ответе

lourence

23:59, 8th August, 2020

Я предлагаю разрубить проблему на части.
Во-первых, найти способ воспроизвести проблему 100% времен и быстро. Опустите таймер, чтобы службы запускались чаще (например, в 10 раз быстрее, чем обычно). Если проблема возникает в 10 раз быстрее, то это связано с количеством итераций, а не с Реальным временем или реальной работой, выполняемой службами). И вы сможете делать следующие шаги быстрее, чем один раз в день.
Во-вторых, закомментируйте весь реальный рабочий код, а пусть только сервисы, таймеры и механизм синхронизации. Если проблема все же появится, то она будет в этой части кода. Если это не так, то начните добавлять обратно код, который вы закомментировали, по одному куску за раз. В конце концов, вы должны выяснить, какая часть кода вызывает проблему.


  Сведения об ответе

nYU

02:42, 6th August, 2020

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

Мое первое предположение заключается в том, что ваши службы могут иметь некоторые ошибки либо в том, как они обрабатывают память, либо, возможно, в том, как они обрабатывают неуправляемую память. В последний раз, когда я отследил подобную проблему, оказалось, что 3rd party OSS libray мы использовали сохраненные дескрипторы для неуправляемых объектов в статической памяти. Чем дольше служба работала, тем больше ручек она поднимала, что заставляло производительность процесса CPU очень быстро нырять носом. Способ попытаться решить такого рода проблему, чтобы гарантировать, что ваши службы ничего не хранят в памяти между вызовами таймера, хотя если ваши сторонние библиотеки используют статическую память, вам, возможно, придется сделать что-то умное, например, создать домен приложения для вызова таймера и выбросить приложение doamin (и его статическую память) после завершения обработки.

Другая проблема, которую я видел в подобных обстоятельствах, заключалась в том, что код синхронизации таймера был подозрительным, что фактически позволяло нескольким потокам выполнять код обработки одновременно. Когда мы отладили код, мы обнаружили, что 1-й поток блокирует 2-й, и к тому времени, когда 2-й стартовал, был заблокирован 3-й. Со временем блокировка длилась все дольше и дольше, и использование CPU, таким образом, направлялось к вершине. Решение, которое мы использовали для устранения этой проблемы, состояло в том, чтобы реализовать правильный код синхронизации, чтобы таймер только запускал другой поток, если он не будет заблокирован.

Надеюсь, это поможет, но заранее приношу свои извинения, если обе мои мысли-пустая болтовня.


  Сведения об ответе

LIZA

05:17, 23rd August, 2020

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

Я бы предложил провести рефакторинг таймера. Замените его одним потоком, который выстраивает работу в очередь на ThreadPool. Вы можете Sleep() поток, чтобы контролировать, как часто он ищет новую работу. Убедитесь, что это единственное место, где ваш код многопоточен. Все остальные объекты должны быть созданы по мере подготовки работы к обработке и уничтожены после завершения этой работы. Государство-это враг в многопоточном коде.

Еще одна область, в которой отсутствует дизайн, по-видимому, заключается в том, что у вас есть несколько служб, которые опрашивают ресурсы для выполнения каких-либо действий. Я бы предложил объединить их под одной службой. Они могут делать отдельные вещи, но они работают в унисон; вы просто используете файловую систему, базу данных и т. д. В качестве замены вызовов методов. Тоже 2003 год? Мне очень жаль тебя.


  Сведения об ответе

LIZA

01:52, 24th August, 2020

Хорошие предложения, но rest уверены, что мы испробовали все обычные способы устранения неполадок. Я надеюсь, что это проблема .NET, о которой кто-то может знать, и мы сможем работать над ее решением.

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

Поскольку это вопрос производительности, хорошие измерения бесценны. Общий процесс CPU использования является слишком широким измерением. Где ваша служба проводит свое время? Вы можете использовать профилировщик для измерения этого или просто регистрировать различные начала и остановки секций. Если вы не в состоянии сделать даже это, то воспользуйтесь предложением Андреа Бертани-изолируйте разделы, удалив другие.

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

Если вы на самом деле уже сделали все это обычное устранение неполадок, пожалуйста, сообщите нам об этом секрете.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться