Azure Web App (ASP.NET MVC) становится холодным каждые десять минут и занимает + 10-20 с для загрузки
У меня очень странная проблема с Azure Web App, и я очень расстраиваюсь.
Мы используем наше приложение очень быстро и быстро реагируем на это, однако, если мы не используем его примерно десять минут, он имеет очень холодный старт (~ 10-20 секунд). Это холодное начало происходит только тогда, когда оно связано с базой данных. Когда это немного напоминает, когда мы выпускаем веб-приложение.
Наши попытки
Используя Application Insights внутри Azure, мы настраиваем этот ping каждые 5 минут:
Выбросы всегда вызваны моими развертываниями (без использования слотов для развертывания прямо сейчас). Однако эта страница входа не вызывает нашу базу данных, поэтому мы не видим "холодного" начала в этих данных.
Настройка приложения должна быть прочной. Наше веб-приложение размещено в Северной Европе с Always on
:
Мы просто перенесли все настройки в новый план обслуживания ресурсов/приложений, чтобы убедиться, что наша проблема запуталась с другими нашими приложениями. Новый план обслуживания приложений - это Standard 1 small
, который не должен быть проблемой. Глядя на наше потребление, я не беспокоюсь и, возможно, даже попробую меньшую услугу, которую я буду делать после решения нашей проблемы:
Наша база данных SQL также размещена в Северной Европе (проверенные местоположения в миллиард раз, потому что я сделал эту ошибку раньше).
Как и в случае с сервисом приложений, мы выбрали "слишком большое" аппаратное обеспечение, чтобы убедиться, что это не вызывает проблемы (стандартные S0: 10 DTU). Использование смехотворно низкое:
Мы используем непрерывное развертывание (Deployment options
в меню Azure), но, глядя на развертывания, он не должен постоянно развертывать что-то:
Фрустрация приходит в приложение супер отзывчив, когда он работает. Когда он "нагревается", каждая страница загружается за считанные секунды, так же как мое среднее время отклика отображается в нашем веб-приложении:
Но эти цифры просто неверны, когда мы (или наши пользователи!) Используем наше приложение. Здесь мы очень часто ощущаем нагрузку + 10-20 секунд в первый раз.
Кто-нибудь имеет ЛЮБОЕ представление? Любые намеки? Вы не представляете, насколько я благодарен.
EDIT & UPDATE 1:
Я решил настроить еще несколько тестов. Теперь мне удалось получить реальные данные, показывающие нашу проблему, вызвав другую страницу. По иронии судьбы, эта страница НЕ вызывает базу данных, поэтому, хотя я думал, что это проблема с базой данных, это не похоже на это. См. Вызов здесь (тенденция продолжается +24 часов).
Странно, насколько стабильно это составляет ровно ~ 10 секунд. И тренд, кажется, не каждые 10-20 минут, но ближе к каждым 5 минутам - с точно таким же интервалом между ними:
EDIT & UPDATE 2:
Я копаю еще. Оказывается, есть пара очень интересных историй: "медленные" 11 секундные вызовы из edit 1, это только из восточных стран США и с одной конечной точки (http://prntscr.com/jcv69w) и
Самое интересное, что я нашел, это следующее:
У самого приложения нет кэширования. Я использую Entity Framework, который, как я предполагаю, использует некоторое кэширование, но все.
Я зашел в наше приложение и щелкнул его в Chrome. Я узнал, что страницы, которые я уже посетил, показывали мгновенно (с данными из БД), но если бы я открывал новую страницу, она медленно загружалась. Казалось, что некоторые объекты кэшируются при первом открытии страницы.
Затем я попытался открыть приложение в новом браузере. Если бы я открыл страницу, которую раньше открывал в Chrome, она открывалась бы мгновенно. Если бы я открывал новую страницу, которую я раньше не нажимал, она имела бы нагрузку ~ 10 секунд.
Мое лучшее предположение прямо сейчас заключается в том, что я использую структуру Entity Framework, которая почему-то дает проблемы.
ИЗМЕНИТЬ 3:
Просто добавил щедрость и настраивает много протоколирования. Я добавил MiniProfiler, но не могу заставить его работать на производстве (отображается только по местным запросам).
Я также добавил регистрацию в global.asax для Application_Start
и Application_BeginRequest
и Application_EndRequest
чтобы увидеть некоторые и статус там. Скоро будет обновляться с выводами.
EDIT 4:
Итак, теперь у меня есть первые интересные номера. Приложение не перерабатывается. Application_Start
вызывается только один раз.
Я вижу разницу во времени, войдя в EndRequest
и BeginRequest
. Я вижу, что есть несколько вызовов, которые занимают больше, чем +15 секунд между этими двумя... Но когда сайт теплый, он занимает ~ 0,5-2 секунды в зависимости от страницы. Поэтому между началом и концом запроса происходит что-то очень странное. Отладка дальше!
EDIT 5:
Получил MiniProfiler для работы. Ниже приведен пример медленной нагрузки (~ 15 секунд):
Следующим шагом является добавление отслеживания Entity Framework и даже еще одна строка для линейных вызовов. Я получаю деньги в базе данных!
EDIT 6:
Окидоки, я был неправ. это метод рендеринга, который замедляется - не база данных! Я не знаю, как отладить это... В google!
EDIT 7:
Время для другого обновления. Статус: ничего не было решено.
Поэтому я пробовал много вещей:
1) Я попытался отключить все типы кэширования (предотвращение кеширования в ASP.NET MVC для определенных действий с использованием атрибута), и у меня такое же поведение. Первая загрузка? Медленный. Следующая нагрузка? Быстро. Подождите 5-10 минут, такое же поведение так не решено.
2) У меня были некоторые пользовательские вещи в моем файле startup.auth с 5-минутной задержкой. Удалены. Не проблема.
3) Я использовал пользовательский атрибут для авторизации. Я удалил это.
4) Я обновил свою реализацию Entity Framework, чтобы она работала за каждый запрос.
Я очень расстраиваюсь. Следующий шаг:
A) Попробуйте сделать 5-10 версий одной и той же страницы (без _layout, с макетом, с базой данных, без базы данных, с инъекцией зависимостей, без... все эти вещи), поэтому см., Могу ли я найти шаблон.
B) Попробуйте переместить хостинг на виртуальную машину, чтобы узнать, разрешает ли она проблему
EDIT 8 - НОВАЯ РЕЛИКСА ДОБАВЛЕНА:
Теперь я добавил новую реликвию. Две очень страшные вещи следующие (я нашел и воспроизвел ошибку!):
И интерфейсный мудрый (часть браузера New Relic), есть недостаток ~ 15s между двумя запусками:
http://prntscr.com/jevgeg vs http://prntscr.com/jevgix, в котором нет ничего.
Ответы
Ответ 1
Я отправляю ответ, хотя он не решен, но я на 99% уверен, что нашел основную проблему.
Случается, что когда я выпускаю, каждое представление должно быть построено. Для создания представления требуется ~ 15 секунд, что и показывает новое реликвии в моем последнем обновлении.
Это приводит к двум временным решениям и к одному большему вопросу: почему создание представления так медленно?
Временные решения просты. Скомпилируйте представления при выпуске или просмотрите наиболее важные страницы сразу после выпуска. Это явно раздражает, потому что я выпускаю несколько раз в день.
Я предполагаю, что причина настолько медленная, потому что я использую очень большую тему Bootstrap. То, как я обрабатываю пакеты, не очень эффективно, что может стать проблемой.
Причина, по которой я считала, что боль была сайтом, была медленной через ~ 10 минут, была просто потому, что я часто выпускал новый код и не посещал большую часть наших страниц. После этого быстро.
Большое спасибо за вашу помощь и поддержку - по крайней мере сейчас я могу справиться с этим.
Ответ 2
У меня есть несколько возможных ответов.
Entity framework-first/database initialization: если вы используете первую настройку кода с миграциями и, возможно, данные семени, каждая из этих вещей может вызвать некоторые проблемы с "разминкой".
Если вы не инициализируете базу данных при запуске приложения, это означает, что при первом запуске вашей базы данных, когда она инициализируется.
Версия фреймворка сущности : сама инфраструктура Entity также имела много улучшений производительности в 5 и 6.x, некоторые из них также связаны с холодными и теплыми скоростями запуска.
Представления не предварительно скомпилированы: если вы получаете медленные нагрузки на страницы (например, после развертывания), каждый первый клик на новой странице (просмотр), а затем последующие загрузки прекрасны. Это может быть связано с тем, что страницы не скомпилированы, я могу подробно остановиться на этом, если это так.
Recycle. Похоже, что вы испытываете эти проблемы, когда приложение перерабатывается, и это не автоматическая инициализация (именно поэтому вы получаете этот холодный удар) худшие проблемы с производительностью, которые я видел с этими вещами, обычно связаны с инфраструктурой сущностей и связаны с прекомпиляцией. Но оба могут быть легко исправлены. Но обеспечение того, что приложение "всегда работает" и само инициализируется после утилизации, также гарантирует, что ни один пользователь не получит этот холодный удар.
ОБНОВЛЕНИЕ: Поскольку это было связано с просмотром, я могу предложить решение, которое я нашел очень полезным. Установка пакета RazorGenerator.Mvc Nuget. И добавление этого движка в качестве первого движка обеспечит использование скомпилированных представлений.
В App_Start
вы можете создать файл RazorGeneratorMvcStart.cs
с таким содержимым:
using RazorGenerator.Mvc;
[assembly: WebActivatorEx.PostApplicationStartMethod(typeof(MyNamespace.RazorGeneratorMvcStart), "Start")]
namespace MyNamespace {
public static class RazorGeneratorMvcStart {
public static void Start() {
ViewEngines.Engines.Insert(0, new PrecompiledMvcEngine(typeof(RazorGeneratorMvcStart).Assembly));
VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);
}
}
}
Двигатель бритвы может даже принимать параметр UsePhysicalViewsIfNewer
для тех, кто любит замену просмотра вживую. В этом случае он использует предварительно скомпилированную версию, если в папке не было установлено представление с более новой датой, чем скомпилированная.dll.
Такой подход должен решать проблемы производительности с помощью представлений.
Ответ 3
Несколько идей:
-
В своем блейджете веб-приложения перейдите в меню "Диагностика и решение проблем". Затем нажмите на счетчики производительности. Я честно прохожу через каждый из доступных перманентных счетчиков, обращая внимание на временную шкалу против вашей деградирующей производительности. Однажды я узнал, что SignalR забивает мой сервер из-за безуспешных соединений, просматривая количество потоков.
-
Ошибки сервера регистрируются в Application Insights?
-
На экране "Диагностика и решение проблем" вы видите что-либо подозрительное в журналах трассировки неудачных запросов?
Ответ 4
- Отделяйте все от развертывания и локального. Если приложение работает отлично в локальной среде, то происходит что-то другое, когда оно идет на Azure. Решение чего-то занимает много времени.
- Любой статический ресурс (сценарий, стили и т.д.) Действительно автоматически кэшируется браузером по первому запросу, поэтому при последующем запросе проблема не должна возникать.
- Поскольку вы знаете, что метод "Render" дает проблему, выглядит как сложное вычисление гнездования и манипуляция DOM браузера. Однако, если это не проблема, когда на локальном компьютере, то проверяйте, обращаются ли вызовы к внешним ресурсам и получают ли они блокирующие вызовы (может потребоваться интенсивное использование асинхронных вызовов ajax или серверной стороны, хотя я предполагаю, что у вас уже есть это на месте.)
- Возможно, потребуется рефакторинг (чтобы иметь меньшие стеки и возможное использование многопоточного/неблокирующего ввода-вывода), однако вам нужно, чтобы ваш код предлагал на этом.
Разделите событие загрузки страницы и любые последующие вызовы, сделанные им. Также как визуализируется представление вместе с любой обработкой DOM.
Ответ 5
Есть еще два варианта поиска и исправления.
1. Пользовательская новая реликвия для отслеживания.
Проверьте это сообщение от hanselman на его использование в Azure
.
2. Следите за лучшей практикой Asp.Net MVC
Проверьте этот пост для лучших практик.
Также для чтения данных вы можете использовать ADO.NET
с хранимыми процедурами вместо Entity Framework
, потому что на данный момент EF
может иметь некоторые проблемы с производительностью.
Ответ 6
Вы компилируете Less или Sass в настройке комплектации?
Если да, то какой JavaScriptEngineSwitcher вы используете?
Я помню, что у меня была аналогичная проблема. Пакеты скомпилированы при первом доступе, и это заняло огромное количество времени.
Решением было перейти на двигатель V8.
Ответ 7
Я понимаю, что прошло чуть больше года для этой темы, но у меня возникла та же проблема в службах приложений Azure. Какой-то десятиминутный тайм-аут, который заставляет всех, кто обращается к приложению, ждать от десяти до тридцати секунд, пока что-то внутреннее перестраивается или переподключается.
В журналах IIS я обнаружил, что каждые десять минут к моей службе приложений отправляется пинг с чего-то под названием ReadyForRequest/1. 0+. Я не могу найти дополнительную информацию об этом запросе в Интернете, но он точно совпадает с нашей десятиминутной проблемой тайм-аута. Мы создали службу поддержки активности, которая посещает наш сайт каждую минуту, и сообщает о времени отклика. Каждые десять минут время отклика изменяется от 0,3 до 10-15 секунд, и это точно соответствует времени этих вызовов ReadyForRequest.
Обычно мы получаем один вызов ReadyForRequest/1. 0+ (LocalCache) и три вызова ReadyForRequest/1. 0+ (AppInit).
GET / - 80 - 10.0.208.4 ReadyForRequest/1.0+(LocalCache)
GET / - 80 - 10.0.208.4 ReadyForRequest/1.0+(AppInit)
У нас есть запрос к нашему представителю Microsoft, но пока они также не могут определить, что вызывает эти звонки.
Может быть, кто-то еще увидит это и получит дальнейшее понимание будущих искателей решений.