Непоследовательность запросов в ASP.NET WebAPI и IIS
Проблема
Я тестирую производительность одного из наших приложений AngularJS + ASP.NET WebAPI. Странная вещь, которую я наблюдаю, заключается в том, что точно такие же запросы выполняются с разными таймингами в Fiddler.
Это поведение наблюдается не только на сервере, но и на моей локальной машине.
Подробнее
Приложение проверяется с помощью Chrome и записывается в ASP.NET WebAPI (Microsoft.AspNet.WebApi version 5.2.2
) с помощью Angular JS version 1.3.8
.
Сервер - это Windows Server 2008 R2 с SQL Server 2008 и IIS 7.5.
Мой локальный компьютер - это Windows 8.1 с Visual Studio 2013 и SQL Server 2014.
Я заметил, что одни и те же запросы выполняются с разными таймингами в соответствии с Fiddler (запросы в синем одинаковы, а запросы в белом - это еще один тип точных запросов):
![Fiddler requests]()
Например, детальное время запроса номер запроса 26:
Request Count: 1
Bytes Sent: 583 (headers:517; body:66)
Bytes Received: 3,844 (headers:260; body:3,584)
ACTUAL PERFORMANCE
--------------
ClientConnected: 17:26:25.099
ClientBeginRequest: 17:27:26.544
GotRequestHeaders: 17:27:26.544
ClientDoneRequest: 17:27:26.544
Determine Gateway: 0ms
DNS Lookup: 0ms
TCP/IP Connect: 0ms
HTTPS Handshake: 0ms
ServerConnected: 17:26:25.102
FiddlerBeginRequest: 17:27:26.544
ServerGotRequest: 17:27:26.544
ServerBeginResponse: 17:27:26.554
GotResponseHeaders: 17:27:26.554
ServerDoneResponse: 17:27:26.554
ClientBeginResponse: 17:27:26.554
ClientDoneResponse: 17:27:26.554
Overall Elapsed: 0:00:00.010
И подробные тайминги номера запроса 28:
Request Count: 1
Bytes Sent: 583 (headers:517; body:66)
Bytes Received: 3,844 (headers:260; body:3,584)
ACTUAL PERFORMANCE
--------------
ClientConnected: 17:26:25.099
ClientBeginRequest: 17:27:29.104
GotRequestHeaders: 17:27:29.104
ClientDoneRequest: 17:27:29.104
Determine Gateway: 0ms
DNS Lookup: 0ms
TCP/IP Connect: 0ms
HTTPS Handshake: 0ms
ServerConnected: 17:26:25.102
FiddlerBeginRequest: 17:27:29.104
ServerGotRequest: 17:27:29.104
ServerBeginResponse: 17:27:29.616
GotResponseHeaders: 17:27:29.616
ServerDoneResponse: 17:27:29.616
ClientBeginResponse: 17:27:29.616
ClientDoneResponse: 17:27:29.616
Overall Elapsed: 0:00:00.512
И как я уже сказал, это точно такие же запросы (одни и те же заголовки, одни и те же данные и т.д.).
Запрос 28 выполняется через 1-2 секунды после запроса 26.
Вопросы
Что может быть основной причиной такого поведения? Где я должен искать проблему? Странная вещь заключается в том, что запрос сначала быстрый, а затем медленный, а затем снова быстрый и т.д. Для меня нет оснований полагать, что проблема связана с кэшированием данных.
Как точно проверить тайминги на сервере, чтобы найти это различие между 0.010
и 0.512
секунд? Разница более 50 раз.
Ответы
Ответ 1
Это не проблема с angular, но вот как я могу решить эту проблему:
- Используйте что-то вроде этого chrome extension для клиента REST API, чтобы делать запросы к вашей конечной точке. (вы также можете использовать что-то вроде: http://jmeter.apache.org/, но это сложнее настроить)
- Запустите это 20 раз и сохраните время.
- Очистить базу данных и просто заполнить таблицы, которые вам нужны для этого запроса - всего несколько строк данных.
-
Запустите инструмент 20 раз - сохраните время. Согласуются ли они? Если в этот момент они не согласуются, я бы посмотрел на код как на виновника.
- Вы вызываете какие-либо внешние службы?
- является ли служба, выполняющая что-либо еще при загрузке данных, помимо выполнения запроса?
- используйте профайлер, например dotTrace, чтобы узнать, что занимает больше времени, чем нужно. (на самом деле вы должны использовать это с самого начала)
-
Если время по-прежнему непротиворечиво, загрузите больше данных в базу данных до тех пор, пока время не станет непоследовательным. Затем профилируйте запросы и начните их оптимизацию.
Прямо сейчас, насколько несовместимы тайминги, я бы предположил, что служба делает что-то еще при загрузке этих данных: внешний вызов службы.. что-то.
Ответ 2
Хорошо, было бы очень полезно, если бы вы могли поделиться с нами кодом, который выполняется на сервере, и какова разница между нечетными и четными запросами.
Я делаю здесь много предположений, поэтому, пожалуйста, извините любые глупые ошибки.
Я видел такое поведение до, в этом случае это связано с SqlServer Caching.
В кратчайшие сроки вы можете найти много информации об этом в Интернете, прежде чем выполнять запрос, который движок SqlServer выполняет некоторые вычисления, и решить, какой оптимальный способ получить данные для этого запроса. Это добавляет дополнительную нагрузку на ваше время запроса, SqlServer знает это и кэширует этот план выполнения, чтобы он мог повторно использовать его позже.
Я не знаю всех подробностей об этом, но если бы я должен был догадаться, я бы сказал, что что-то делает недействительным этот кеш, поэтому его нужно пересчитывать каждый раз в то время. Общими причинами этого могут быть разные предложения order by
и join
, которые могут произойти в зависимости от данных, отправленных методу.
Другая возможность заключается в том, что сам результат кэшируется, и через некоторое время он становится недействительным.
Как я уже сказал, это дикое предположение, не глядя на код, но я действительно думаю, что было бы неплохо проверить это.
Один простой способ проверить это - проверить, не меняется ли время, если вы отправляете один и тот же запрос снова и снова, повторно, без отправки другого. Тем временем
Надеюсь, что это поможет.
Ответ 3
Вы пишете "те же самые запросы", но что именно происходит в этих запросах?
Вы запрашиваете базу данных SQL-сервера?
Как выглядит выражение?
Что еще вы делаете в своем запросе?
Есть так много возможных влияний, поэтому для того, чтобы сделать обоснованное предположение, мне понадобится более подробная информация о ваших запросах.
Ответ 4
Несколько вещей, чтобы проверить/отметить:
1). Установили ли вы Glimpse? http://getglimpse.com/, если бы я не установил это из nuget, это даст вам представление о полном конвейере и поможет вам отслеживать, куда идут эти задержки из.
*** более общие рекомендации по производительности ниже **
2). у вас есть отладка отключена в веб-конфигурации для публикации на вашем сервере? если не сделать это первым. Я ожидал бы, что ваш локальный компьютер будет немного отличаться от сервера, я полагаю, вы используете iis express на своем локальном компьютере? который имеет разные характеристики производительности, чем iis на сервере (я бы этого не ожидал), поэтому не следует чрезмерно руководствоваться этим. Glimpse будет вашим лучшим другом здесь:-)
3). Как и выше, то же самое относится к состоянию сеанса. Если у вас нет оснований для его использования, отключите его (по умолчанию он включен) - в некоторых сценариях это может быть убийца производительности.
Ответ 5
Скорее всего, вы видите одно из следующих:
-
Перезагрузка/очистка пула приложений IIS (это может произойти, когда настройка будет перезаписана, когда все будет закрыто)
-
Коллекция GC GC (маловероятная)
-
Задержки, связанные с SQL Server (выполнение кеширования выполнения запросов и данные в памяти)
Чтобы исключить действие # 3, попробуйте запустить профилировщик SQL Server одновременно с файрволом и посмотрите, можете ли вы определить задержку из базы данных (либо она подтвердит это в базе данных, либо подтвердит, что база данных отвечает то же самое в обоих случаях).
С# 2 не так много, что вы действительно можете сделать, кроме как попытаться уменьшить объем памяти и повторное использование структур данных; но, как упоминалось выше, это вряд ли может быть причиной проблемы.
С# 1 вы можете внести изменения в конфигурацию IIS, чтобы убедиться, что этого не происходит.