Я реализовал ряд сервисов в веб-API asp.net. Я применил ActionFilterAttribute для измерения производительности на сервере:
public class PerformanceActionFilterAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
actionContext.Request.Properties[StopwatchKey] = Stopwatch.StartNew();
base.OnActionExecuting(actionContext);
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
var stopwatch = (Stopwatch) actionExecutedContext.Request.Properties[StopwatchKey];
if(actionExecutedContext.Response != null)
actionExecutedContext.Response.Headers.Add("ServerTimeMs", stopwatch.ElapsedMilliseconds.ToString());
base.OnActionExecuted(actionExecutedContext);
}
}
Вышеприведенный код отправляет время на сервер обратно клиенту в качестве заголовка. Этот заголовок показывает очень хорошую производительность для всех вызовов службы. Обычно ниже 100 мс. Когда нагрузка на сервер растет, я продолжаю получать хорошие результаты из вышеперечисленных измерений, но производительность, которую я испытываю в браузере, плоха. Я получаю "время ожидания" выше 10 секунд. Даже при довольно низкой нагрузке, как видно на этом снимке экрана из Chrome:
Я использую сервер Windows 2012.
До сих пор я пришел к выводу, что это не мой код, который требует много времени для выполнения. Но что же тогда? И как мне расследовать эту проблему?
(Я также попытался измерить производительность, используя Application_BeginRequest
и Application_EndRequest
в Global.asax. Он дает примерно одинаковые значения.)
Изменение: Некоторая дополнительная информация из случайного запроса, записанного скрипачом. Обратите внимание на длительный разрыв между ClientConnected
и ClientBeginRequest
:
ClientConnected: 19:20:58.835
ClientBeginRequest: 19:21:06.928
GotRequestHeaders: 19:21:06.928
ClientDoneRequest: 19:21:06.928
Determine Gateway: 0ms
DNS Lookup: 0ms
TCP/IP Connect: 0ms
HTTPS Handshake: 0ms
ServerConnected: 19:20:53.769
FiddlerBeginRequest:19:21:06.928
ServerGotRequest: 19:21:06.929
ServerBeginResponse:19:21:07.043
GotResponseHeaders: 19:21:07.043
ServerDoneResponse: 19:21:07.043
ClientBeginResponse:19:21:07.043
ClientDoneResponse: 19:21:07.043
После более пристального просмотра счетчиков производительности на сервере, я вижу, что время выполнения на самом деле очень низкое. Но около 400 запросов пр. во-вторых, IIS начинает очереди запросов.
Поэтому ответ на мой вопрос должен состоять в том, что, помимо выполнения моего кода, запрос тратит много времени в очереди. Очередь начинается, но время выполнения каждого запроса все еще очень низкое.
Это приводит к новому вопросу. Как оптимизировать мое приложение или настройку сервера, чтобы увеличить предел. Но это еще одна история.