Понимание BLOCKED_TIME в PerfView

#asp.net-core #.net-core #perfview

#asp.net-ядро #.net-ядро #пул потоков #perfview #голодание

Вопрос:

Мы подозреваем, что испытываем нехватку пула потоков на сервере, на котором выполняется пара ASP.NET Основные API и пара консолей .NET Core.

Я запустил perfview one на одном из наших серверов, когда мы подозревали проблемы с нехваткой пула потоков. Однако у меня возникли небольшие проблемы с анализом результатов.

Я работал PerfView /threadTime collect около 60 секунд. И вот результат, который я получил (я выбрал его, чтобы посмотреть на один из наших ASP.NET Основные API):

введите описание изображения здесь

Глядя на «По имени», мы можем видеть, что много времени тратится на BLOCKED_TIME . Если я дважды щелкну, то перейду к следующему представлению, где я могу развернуть один из узлов, чтобы получить следующее представление (перезаписанная часть — это название нашего процесса API):

введите описание изображения здесь

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

Есть ли какие-либо другие выводы, которые мы можем сделать из этого?

Ответ №1:

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

В общем, если вы испытываете нехватку потоков, первое, на что вам следует обратить внимание, — это использование пула потоков. Используете ли вы асинхронность везде, где только можете? Делаете ли вы вещи, которые являются большими запретами в веб-приложениях, такие как использование Task.Run , Task.StartNew или хуже, Thread.Start ? Все эти созданные потоки выходят из одного пула потоков и, таким образом, пропорционально снижают пропускную способность вашего сервера.

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

Если не считать всего этого, возможно, вы просто получаете больше нагрузки, чем сервер может обрабатывать в целом. Это всегда возможно. Возможно, вам нужно масштабировать системные ресурсы по вертикали (и пул потоков вместе с ним). Возможно, вам нужно масштабировать по горизонтали, реплицируя этот сервер с балансировщиком нагрузки впереди. Учитывая, что вы запускаете несколько разных функций на одном сервере, простой способ горизонтального масштабирования — просто разделить эти функции на их собственные компьютеры. Одно это, вероятно, оказало бы огромную помощь. Однако масштабирование по вертикали или горизонтали должно быть вашим последним средством. Сначала убедитесь, что вы используете ресурсы эффективно, прежде чем тратить больше ресурсов на свои неэффективные вещи.

Комментарии:

1. Спасибо! Я забыл упомянуть, что причина, по которой я подозревал нехватку пула потоков, заключалась в том, что я мог видеть, что примерно два потока ne запускались каждую секунду, как упоминалось в этой статье: blogs.msdn.microsoft.com/vancem/2018/10/16 /… . Мы не используем Task. Запуск или что-то в этом роде, но я бы сказал, что наш ввод-вывод 50/50 с использованием асинхронности по сравнению с синхронизацией. Например, ToListAsync против ToList в Entity Framework

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

3. ДА. Это именно то, что это такое. PerfView не указывает, что вызывает простаивание потока, только то, что он простаивает. Если вы хотите больше деталей, я бы посоветовал добавить более обширное ведение журнала в ваше приложение, чтобы вы могли определять время между различными этапами выполнения вашего кода.