Понимание BLOCKED_TIME в PerfView - PullRequest
       69

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

1 голос
/ 08 марта 2019

Мы подозреваем, что испытываем истощение пула потоков на сервере, на котором работает пара API-интерфейсов ASP.NET Core и пара консолей .NET Core.

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

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

enter image description here

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

enter image description here

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

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

1 Ответ

2 голосов
/ 08 марта 2019

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

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

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

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

...