Веб-служба ASMX замедляет первый запрос - PullRequest
23 голосов
/ 24 апреля 2009

У меня есть несколько веб-сервисов .NET, работающих в одном приложении IIS. Эти веб-сервисы используются другим приложением IIS (веб-интерфейс). Первый звонок довольно медленный, около 5-10 секунд. После этого это просто миллисекунды. Первый вызов считается проблемой производительности.

Мы пробовали приложение, которое вызывает все эти веб-сервисы, но это, очевидно, ничего не решает. Так что проблема не в утилизации приложений по умолчанию. Я создал приложение, которое просто инициализирует службу несколько раз и измеряет время, необходимое для создания одного экземпляра. Перед запуском этого приложения я проверяю, что мое приложение веб-службы запущено / переработано, а затем я запускаю приложение. Первая инициализация занимает от 2 до 4 секунд, все остальные только миллисекунды.

Другая мысль состоит в том, что мы создаем страницу в приложении Frontend, которая запускает все веб-сервисы, и что мы вызываем эту страницу до того, как в нее войдут пользователи. Я не считаю это элегантным решением, что еще можно попробовать?

Ответы [ 7 ]

34 голосов
/ 25 апреля 2009

Задержка, возникающая при первом вызове клиентом веб-службы, вызвана тем, что по умолчанию необходимо скомпилировать dll XmlSerializer для веб-службы. Это вызывает 2-4 секунды для первоначального вызова. Конечно, это тот случай, когда приложение веб-сервиса уже запущено, в противном случае вы бы перезапустили его. В этом случае другие ответы могут помочь.

Чтобы ускорить начальный вызов, вы можете создать dll XmlSerializer во время компиляции. Вы можете сделать это, включив сборку проекта «Создать сборку сериализации». Это создает MyApplication.XmlSerializers.dll, содержащую информацию веб-службы. Теперь первоначальный вызов упал до 300 мс, предположительно загрузка DLL. Все звонки после приема занимают 0 мс.

В Visual Studio щелкните правой кнопкой мыши свой проект и выберите «Свойства». Перейдите на вкладку «Сборка». Там у вас есть опция «Создать сборку сериализации» в разделе «Вывод». Если вы измените значение на «On», сборка сериализации будет сгенерирована во время компиляции.

9 голосов
/ 24 апреля 2009

При первом вызове веб-службы или в первый раз после длительной задержки веб-служба должна быть запущена. Здесь вы видите задержку. После этого он уже запущен и будет очень быстро отвечать на звонки. Это стандартное поведение веб-службы.

Вы можете настроить IIS так, чтобы keepalive = true, что может повысить производительность.

Более подробная информация по запросу.

Возможно, сборки сериализации создаются во время выполнения. Вы можете изменить параметры сборки сериализации, используя раскрывающийся список внизу панели «Сборка» окна свойств проекта.

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

Возможно, операция выполняется очень медленно, но вы затем кэшируете ответ, что ускоряет последующие вызовы.

5 голосов
/ 13 августа 2009

Недавно я обнаружил, что в наших ASMX-файлах мы ссылаемся только на имя класса. Мы получили реализацию сервиса в отдельной сборке для каждого ASMX-файла. Это заставляет .NET Framework сканировать всю папку bin в поисках сборки, содержащей реализацию. По мере роста вашего приложения веб-сервиса это будет занимать больше времени. Эту проблему можно решить не только включив имя класса в определение ASMX, но и имя сборки.

Наш ASMX выглядел так:

<%@ WebService Language=”C#” CodeBehind=”MyService.cs” Class=”MyWebservice” %>

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

<%@ WebService Language=”C#” CodeBehind=”MyService.cs” Class=”MyWebservice, MyWebservice.Implementation.Assembly” %>

4 голосов
/ 24 апреля 2009

Это типично, поскольку приложения ASP.NET компилируются и загружают каталог bin \ в память при первом запросе.

Что делать первым:

Удалите все ненужные библиотеки DLL в каталоге bin. (Я видел, как люди отправляют nunit.dll)

Предварительно скомпилируйте приложение ASP.NET, чтобы IIS не нуждался в этом. См. " VS 2008 Развернута поддержка проекта веб-развертывания "

2 голосов
/ 24 апреля 2009

Не уверен, что это решит медленный раскрутку WS в «самый первый раз», так как я предполагаю, что есть нагрузка компиляции и загрузки .NET DLL, но вы можете почти исключить любые будущие холодные запуски, гарантируя пул приложений, в котором находится WS, настроен правильно.

По умолчанию IIS6 имеет «респаун» на холостом ходу, через несколько минут или события «перезапуска», которые эффективно перезапускают WS каждый раз. Если вы довольны стабильным обслуживанием, тогда они не нужны.

Убедительная рекомендация - наличие у WS собственного выделенного пула приложений (не разделяющего неподходящий пул).

1 голос
/ 28 августа 2013

После нескольких часов безумного тестирования я смог сократить время первого запуска веб-сервиса до минимума с двух хостов в одном классе IP (ниже 300 мс) ....

Сначала я испытывал начальную задержку в 2-3 секунды при первом вызове веб-службы, а затем любой последующий вызов из того же процесса был очень быстрым.

Ключ к пониманию задержки в моем случае заключался в том, как клиент обрабатывает WEB-ПРОКСИ !!

Это моя новая привязка в файле app.config:

  <basicHttpBinding>
    <binding name="CreateContextSoap" closeTimeout="00:01:00" openTimeout="00:01:00"
        receiveTimeout="01:00:00" sendTimeout="01:00:00" allowCookies="false"
        bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
        maxBufferSize="16777216" maxBufferPoolSize="524288" maxReceivedMessageSize="16777216"
        messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
        useDefaultWebProxy="false">
      <readerQuotas maxDepth="32" maxStringContentLength="1048576" maxArrayLength="16384"
          maxBytesPerRead="65536" maxNameTableCharCount="16384" />
      <security mode="None">
        <transport clientCredentialType="None" proxyCredentialType="None"
            realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
    </binding>
  </basicHttpBinding>

Первое выполнение веб-вызова, которое я предполагаю, будет намного медленнее, потому что транспортный канал должен обнаружить конфигурацию прокси при инициализации, чтобы прозрачно подключиться к Интернету. Обычно это не требуется в среде интрасети, поэтому я изменил эти параметры привязки, чтобы избежать использования прокси-сервера по умолчанию (автоматически обнаруживается из настроек проводника):

bypassProxyOnLocal = "ложь"

useDefaultWebProxy = "ложь"

Время соединения при первом вызове теперь значительно уменьшено. Надеюсь, это поможет.

0 голосов
/ 06 декабря 2017

Извините за добавление некро, но для меня это тоже постоянная борьба, и я хотел добавить немного информации на картинку. VisualStudio сам добавляет довольно большой компонент ко времени. Вот базовый тест, включающий в себя приложение для создания форм и уже работающий веб-сервис, размещенный внутри на сервере компании (для Generate Serialization Assembly установлено значение true для всех тестов):

Running in VS, Debug:
    First Call: 400 ms to set up client object, 450 to call function
    Second Call: 1 ms to set up client object, 14 to call function
Running as .exe, Release:
    First Call: 20 ms to set up client object, 70 to call function
    Second call: 1 ms to set up client object, 4 to call function
Running the Debug's .exe file outside of vs:
    First Call: 20 ms to set up client object, 80 to call function
    Second call: 1 ms to set up client object, 4 to call function
Running as Release within VS:
    Similar results to Debug in VS -- very slow

Рассказ? Visual Studio добавляет большую часть времени к картине. Вместо ~ 90 мс, это занимает почти секунду. Поэтому, если вы настраиваете производительность, убедитесь, что вы проводите тестирование вне среды VisualStudio.

...