ASP.NET 애플리케이션에서 웹 서비스를 호출할 때 성능 문제

이 문서에서는 Microsoft ASP.NET 애플리케이션에서 웹 서비스를 호출할 때 발생하는 성능 문제를 해결하는 데 도움이 됩니다.

원래 제품 버전: ASP.NET
원본 KB 번호: 821268

증상

ASP.NET 애플리케이션에서 웹 서비스를 호출할 때 경합, 성능 저하 및 교착 상태가 발생할 수 있습니다. 클라이언트는 요청이 응답을 중지하거나 실행하는 데 시간이 오래 걸린다는 것을 보고할 수 있습니다. 교착 상태가 의심되는 경우 작업자 프로세스가 재활용될 수 있습니다.

메서드를 호출 HttpWebRequest.GetResponse 할 때 다음과 같은 예외 오류 메시지가 표시될 수 있습니다.

"System.InvalidOperationException: ThreadPool 개체에 작업을 완료할 수 있는 여유 스레드가 부족했습니다."

브라우저에서 다음 예외 오류 메시지가 표시될 수도 있습니다.

"HttpException(0x80004005): 요청 시간이 초과되었습니다."

참고

이 문서는 직접 요청을 하는 HttpWebRequest 애플리케이션에도 적용됩니다.

원인

이 문제는 ASP.NET 호출이 요청을 실행하는 데 사용할 수 있는 작업자 스레드 및 완료 포트 스레드 수를 제한하기 때문에 발생할 수 있습니다.

일반적으로 웹 서비스에 대한 호출은 작업자 스레드 1개를 사용하여 요청을 보내는 코드를 실행하고 완료 포트 스레드 하나를 사용하여 웹 서비스에서 콜백을 받습니다. 그러나 요청이 리디렉션되거나 인증이 필요한 경우 호출은 작업자 스레드 2개와 완료 포트 스레드 2개를 사용할 수 있습니다. 따라서 여러 웹 서비스 호출이 동시에 발생할 때 관리 ThreadPool 되는 를 소진할 수 있습니다.

예를 들어 가 ThreadPool 10개의 작업자 스레드로 제한되고 10개의 작업자 스레드가 모두 현재 콜백이 실행되기를 기다리는 코드를 실행한다고 가정합니다. 스레드를 사용할 수 있게 될 때까지 큐에 ThreadPool 대기 중인 작업 항목이 차단되므로 콜백을 실행할 수 없습니다.

경합의 또 다른 잠재적 소스는 maxconnection 네임스페이 System.Net 스가 연결 수를 제한하는 데 사용하는 매개 변수입니다. 일반적으로 이 제한은 예상대로 작동합니다. 그러나 많은 애플리케이션이 동시에 단일 IP 주소에 많은 요청을 시도하는 경우 스레드는 사용 가능한 연결을 기다려야 할 수 있습니다.

해결 방법

이러한 문제를 resolve 위해 Machine.config 파일에서 다음 매개 변수를 조정하여 상황에 가장 잘 맞을 수 있습니다.

  • maxWorkerThreads
  • minWorkerThreads
  • maxIoThreads
  • minFreeThreads
  • minLocalRequestFreeThreads
  • maxconnection
  • executionTimeout

이러한 문제를 성공적으로 resolve 위해 다음 작업을 수행합니다.

  • 동시에 실행할 수 있는 ASP.NET 요청 수를 CPU당 약 12개로 제한합니다.
  • 웹 서비스 콜백이 에서 ThreadPool스레드를 자유롭게 사용할 수 있도록 허용합니다.
  • 매개 변수에 적합한 maxconnections 값을 선택합니다. 사용되는 IP 주소 수 및 AppDomains를 기준으로 선택합니다.

참고

CPU당 ASP.NET 요청 수를 12개로 제한하는 권장 사항은 약간 임의입니다. 그러나 이 제한은 대부분의 애플리케이션에서 잘 작동하는 것으로 입증되었습니다.

MaxWorkerThreads 및 maxIoThreads

ASP.NET 다음 두 가지 구성 설정을 사용하여 사용되는 작업자 스레드 및 완료 스레드의 최대 수를 제한합니다.

<processModel maxWorkerThreads="20" maxIoThreads="20">

maxWorkerThreads 매개 변수와 매개 변수는 maxIoThreads CPU 수를 암시적으로 곱합니다. 예를 들어 프로세서가 두 개 있는 경우 작업자 스레드의 최대 수는 2 * maxWorkerThreads입니다.

MinFreeThreads 및 minLocalRequestFreeThreads

ASP.NET 원격 요청 또는 로컬 요청을 시작하는 데 사용할 수 있어야 하는 작업자 스레드 및 완료 포트 스레드 수를 결정하는 다음 구성 설정도 포함되어 있습니다.

<httpRuntime minFreeThreads="8" minLocalRequestFreeThreads="8">

사용 가능한 스레드가 충분하지 않은 경우 충분한 스레드가 요청을 수행할 수 있을 때까지 요청이 큐에 대기됩니다. 따라서 ASP.NET 동시에 다음 요청 수보다 더 많이 실행되지 않습니다.

(maxWorkerThreads * CPU 수) - minFreeThreads

참고

minFreeThreads 매개 변수와 minLocalRequestFreeThreads 매개 변수는 CPU 수를 암시적으로 곱하지 않습니다.

MinWorkerThreads

ASP.NET 원격 요청을 즉시 서비스할 수 있는 작업자 스레드 수를 결정하는 다음 구성 설정도 포함되어 있습니다.

<processModel minWorkerThreads="1">

이 설정으로 제어되는 스레드는 CLR(공용 언어 런타임)의 기본 스레드 튜닝 기능에서 만든 작업자 스레드보다 훨씬 빠른 속도로 만들 수 있습니다.

이 설정을 사용하면 백 엔드 서버의 속도가 느려지거나 클라이언트 끝의 요청이 갑자기 버스트되거나 큐의 요청 수가 급격히 증가하여 ASP.NET 요청 큐를 갑자기 채울 수 있는 서비스 요청에 ASP.NET 수 있습니다.

매개 변수의 minWorkerThreads 기본값은 1입니다. 매개 변수의 값을 다음 값 minWorkerThreads 으로 설정하는 것이 좋습니다.

minWorkerThreads = maxWorkerThreads / 2

기본적으로 minWorkerThreads 매개 변수는 Web.config 파일 또는 Machine.config 파일에 없습니다. 이 설정은 CPU 수를 암시적으로 곱합니다.

Maxconnection

매개 변수는 maxconnection 특정 IP 주소에 연결할 수 있는 연결 수를 결정합니다. 매개 변수는 다음과 같이 표시됩니다.

<connectionManagement>
    <add address="*" maxconnection="2">
    <add address="http://65.53.32.230" maxconnection="12">
</connectionManagement>

애플리케이션의 코드가 IP 주소 대신 호스트 이름으로 애플리케이션을 참조하는 경우 매개 변수는 다음과 같이 표시됩니다.

<connectionManagement>
    <add address="*" maxconnection="2">
    <add address="http://hostname" maxconnection="12">
</connectionManagement>

마지막으로 애플리케이션이 80 이외의 포트에서 호스트되는 경우 매개 변수는 아래와 유사하게 URL에 비표준 포트를 포함해야 합니다.

<connectionManagement>
    <add address="*" maxconnection="2">
    <add address="http://hostname:8080" maxconnection="12">
</connectionManagement>

이 문서의 앞부분에서 설명한 매개 변수에 대한 설정은 모두 프로세스 수준에 있습니다. 그러나 매개 변수 설정은 maxconnection AppDomain 수준에 적용됩니다. 기본적으로 이 설정은 AppDomain 수준에 적용되므로 프로세스의 각 AppDomain에서 특정 IP 주소에 대해 최대 두 개의 연결을 만들 수 있습니다.

ExecutionTimeout

ASP.NET 다음 구성 설정을 사용하여 요청 실행 시간을 제한합니다.

<httpRuntime executionTimeout="90"/>

속성을 사용하여 Server.ScriptTimeout 이 제한을 설정할 수도 있습니다.

참고

매개 변수 값을 executionTimeout 늘리면 매개 변수 설정을 수정 processModelresponseDeadlockInterval 해야 할 수도 있습니다.

권장 사항

이 섹션에서 권장되는 설정은 모든 애플리케이션에서 작동하지 않을 수 있습니다. 그러나 다음 추가 정보는 적절한 조정을 하는 데 도움이 될 수 있습니다.

각 ASPX 페이지에서 단일 IP 주소로 웹 서비스를 한 번 호출하는 경우 다음 구성 설정을 사용하는 것이 좋습니다.

  • 매개 변수 및 maxIoThreads 매개 변수의 maxWorkerThreads 값을 100으로 설정합니다.
  • 매개 변수 값을 maxconnection12*N 으로 설정합니다(여기서 N 은 사용자가 가진 CPU 수임).
  • 매개 변수의 minFreeThreads 값을 88*N 으로 설정하고 매개 변수를 minLocalRequestFreeThreads76*N으로 설정합니다.
  • 값을 minWorkerThreads50으로 설정합니다. minWorkerThreads 는 기본적으로 구성 파일에 없습니다. 추가해야 합니다.

이러한 권장 사항 중 일부는 서버의 CPU 수를 포함하는 간단한 수식을 포함합니다. 수식의 CPU 수를 나타내는 변수는 N입니다.

이러한 설정의 경우 하이퍼스레딩을 사용하도록 설정한 경우 실제 CPU 수 대신 논리 CPU 수를 사용해야 합니다. 예를 들어 하이퍼스레딩을 사용하도록 설정된 4개 프로세서 서버가 있는 경우 수식의 N 값은 4가 아닌 8이 됩니다.

참고

이 구성을 사용하는 경우 100-88=12이므로 CPU당 최대 12개의 ASP.NET 요청을 동시에 실행할 수 있습니다. 따라서 적어도 88*N 작업자 스레드 및 88*N 완료 포트 스레드는 다른 용도(예: 웹 서비스 콜백)에 사용할 수 있습니다.

예를 들어 4개의 프로세서와 하이퍼스레딩을 사용하도록 설정된 서버가 있습니다. 이러한 수식에 따라 이 문서에 언급된 구성 설정에 다음 값을 사용합니다.

<system.web>
    <processModel maxWorkerThreads="100" maxIoThreads="100" minWorkerThreads="50"/>
    <httpRuntime minFreeThreads="704" minLocalRequestFreeThreads="608"/>
</system.web>
<system.net>
    <connectionManagement>
        <add address="[ProvideIPHere]" maxconnection="96"/>
    </connectionManagement>
</system.net>

또한 이 구성을 사용하는 경우 각 AppDomain의 IP 주소당 CPU당 12개의 연결을 사용할 수 있습니다. 따라서 다음 시나리오에서는 요청이 연결을 대기하고 ThreadPool 가 소진되지 않을 때 경합이 거의 발생하지 않습니다.

  • 웹은 하나의 애플리케이션(AppDomain)만 호스트합니다.
  • ASPX 페이지에 대한 각 요청은 하나의 웹 서비스 요청을 만듭니다.
  • 모든 요청은 동일한 IP 주소에 있습니다.

그러나 이 구성을 사용하는 경우 아래 중 하나를 포함하는 시나리오에서 너무 많은 연결을 사용할 수 있습니다.

  • 요청은 여러 IP 주소에 대한 것입니다.
  • 요청이 리디렉션됩니다(302 상태 코드).
  • 요청에는 인증이 필요합니다.
  • 요청은 여러 AppDomains에서 이루어집니다.

이러한 시나리오에서는 매개 변수에 대해 더 낮은 값 maxconnection 과 매개 변수 및 매개 변수 minLocalRequestFreeThreadsminFreeThreads 더 높은 값을 사용하는 것이 좋습니다.

추가 정보

자세한 내용은 ASP.NET 성능 향상을 참조하세요.

IIS에서 ASP.NET 함께 성능 저하 및 경합이 발생하는 경우 다음 Microsoft 블로그로 이동하세요.