ASP.NET 성능 모니터링 및 관리자에게 경고하는 시기
토머스 마커트
Microsoft Corporation
업데이트 날짜: 2003년 7월
적용 대상:
Microsoft® ASP.NET
요약: Microsoft ASP.NET 애플리케이션에서 스트레스 및 성능 문제를 진단하는 데 가장 유용한 성능 카운터, 관리자에게 문제를 알리기 위해 설정해야 하는 임계값 및 ASP.NET 애플리케이션의 상태를 모니터링하는 데 사용할 수 있는 기타 리소스에 대해 설명합니다. (17페이지 인쇄)
콘텐츠
성능 카운터 모니터링
이벤트 로그 모니터링
W3C 및 HTTPERR 로그 모니터링
ASP.NET 모니터링하는 데 사용되는 기타 리소스
성능 카운터 이해
.NET CLR 예외 카운터
.NET CLR 로드 카운터
.NET CLR 메모리 카운터
ASP.NET 카운터
ASP.NET 애플리케이션 카운터
프로세스 카운터
프로세서 카운터
메모리 카운터
시스템 카운터
웹 서비스 카운터
결론
성능 카운터 모니터링
애플리케이션 모니터링에 사용할 수 있는 많은 성능 카운터가 있습니다. 성능 로그에 포함할 항목을 선택하는 것은 까다로울 수 있으며 이를 해석하는 방법을 배우는 것은 예술입니다. 이 문서는 이러한 두 작업을 더 편안하게 느낄 수 있도록 도와줍니다.
최소한 Microsoft® ASP.NET 애플리케이션에 대해 다음 성능 카운터를 모니터링해야 합니다.
- Processor(_Total)\% Processor Time
- Process(aspnet_wp)\% Processor Time
- Process(aspnet_wp)\Private Bytes
- Process(aspnet_wp)\Virtual Bytes
- Process(aspnet_wp)\Handle Count
- Microsoft® .NET CLR Exceptions\# Exceps throw/ sec
- ASP.NET\애플리케이션 다시 시작
- ASP.NET\요청 거부됨
- ASP.NET\작업자 프로세스 다시 시작(IIS 6.0에는 적용되지 않음)
- Memory\Available Mbytes
- 웹 서비스\현재 연결
- Web Service\ISAPI 확장 요청/초
다음은 성능 모니터링에 유용한 더 큰 성능 카운터 목록입니다. 특히 쉽게 재현할 수 없는 문제가 발생하는 경우 성능 데이터가 충분하지 않은 것보다 더 많은 성능을 갖는 것이 좋습니다. 이 목록에는 일반적으로 필요하지 않은 몇 가지 성능 카운터가 생략됩니다. 예를 들어 세션 상태 및 트랜잭션 성능 카운터는 기능이 사용되는 경우에만 필요합니다.
ASP.NET 애플리케이션 디버깅 및 테스트 경험을 기반으로 몇 가지 임계값을 권장합니다. 이 문서에서 "임계값"을 검색하여 바로 이동할 수 있습니다. 관리자는 이러한 임계값이 환경에 따라 초과될 때 경고를 발생할지 여부를 결정해야 합니다. 대부분의 경우 경고는 특히 임계값이 장시간 초과되는 경우에 적합합니다.
이벤트 로그 모니터링
ASP.NET 및 Microsoft® IIS(인터넷 정보 서버)의 메시지에 대한 이벤트 로그를 모니터링하는 것이 중요합니다. ASP.NET 예를 들어 aspnet_wp 작업자 프로세스가 종료 될 때마다 애플리케이션 로그에 메시지를 씁니다. IIS 6.0은 예를 들어 w3wp 작업자 프로세스가 비정상 또는 크래시를 보고할 때마다 애플리케이션 및/또는 시스템 로그 모두에 메시지를 씁니다. 애플리케이션 로그를 읽고 ASP.NET 및 IIS에서 메시지를 필터링하고 필요한 경우 경고를 발생시키는 .NET 애플리케이션을 쉽게 작성할 수 있습니다(전자 메일을 보내거나 호출기를 다이얼).
W3C 및 HTTPERR 로그 모니터링
먼저 IIS(인터넷 정보 서비스) 관리자를 통해 IIS 5.0 및 IIS 6.0에 대한 W3C 로깅을 사용하도록 설정합니다. 이 로그는 URI, 상태 코드 등과 같은 요청에 대한 다양한 데이터를 포함하도록 구성할 수 있습니다. 로그에서 404 찾을 수 없음과 같은 오류 코드를 검사하고 필요한 경우 링크를 수정하는 작업을 수행합니다. IIS 6.0에서는 하위 상태 코드가 로그에 포함되며 디버깅에 유용합니다. IIS는 하위 통계 코드를 사용하여 특정 문제를 들여쓰기합니다. 예를 들어 404.2는 요청을 처리하는 ISAPI 확장이 잠겨 있음을 나타냅니다. 상태 및 하위 상태 코드 목록은 사용자 지정 오류 메시지 정보 항목에서 찾을 수 있습니다.
IIS 6.0의 새로운 기능, 형식이 잘못되었거나 잘못된 요청 및 애플리케이션 풀에서 제공되지 않는 요청은 HTTP 요청을 처리하기 위한 커널 모드 드라이버인 HTTP.SYS HTTPERR 로그에 기록됩니다. 각 항목에는 URL과 오류에 대한 간략한 설명이 포함됩니다.
HTTPERR 로그에서 거부된 요청을 확인합니다. 커널 요청 큐를 초과한 경우와 신속한 장애 보호 기능을 통해 애플리케이션을 오프라인으로 전환할 때 HTTP.SYS 요청이 거부됩니다. 첫 번째 문제가 발생하면 URL이 QueueFull 메시지와 함께 기록되고 두 번째 문제가 발생하면 메시지는 AppOffline입니다. 기본적으로 커널 요청 큐는 1,000으로 설정되며 IIS 관리자의 애플리케이션 풀 속성 페이지에서 구성할 수 있습니다. 사이트가 매우 높은 부하를 받고 있는 동안 애플리케이션 풀이 충돌하는 경우 커널 요청 큐가 1,000을 쉽게 초과할 수 있으므로 사용 중인 사이트의 경우 이를 5,000으로 늘리는 것이 좋습니다.
작업자 프로세스 충돌 또는 중단으로 인해 손실된 요청은 HTTPERR 로그를 확인합니다. 이 경우 URL은 각 진행 중인 요청에 대해 Connection_Abandoned_By_AppPool 메시지와 함께 기록됩니다. 진행 중인 요청은 처리를 위해 작업자 프로세스로 전송되었지만 충돌 또는 중단 전에 완료되지 않은 요청입니다.
HTTPERR 로그에 대한 자세한 내용은 Microsoft 기술 자료 문서 820729: INFO: HTTP API에서 오류 로깅에서 찾을 수 있습니다.
ASP.NET 모니터링하는 데 사용되는 기타 리소스
성능 카운터 및 이벤트 로그는 발생하는 모든 오류를 catch하지 않으므로 ASP.NET 모니터링하기에 충분하지 않습니다. 하나 이상의 페이지에 대해 HTTP 요청을 보내고 특정 응답을 기대하는 간단한 애플리케이션을 작성하는 것이 좋습니다. 이 도구는 TTLB(마지막 바이트)까지의 시간을 모니터링하여 페이지가 적시에 제공되도록 해야 합니다. 또한 이 정보는 문제를 분석하는 데 필요하므로 발생하는 모든 오류를 기록해야 합니다.
IIS 6.0 리소스 키트에는 로그 파일(W3C 로그, HTTPERR 로그, 이벤트 로그)을 구문 분석하고 결과를 파일 또는 데이터베이스에 저장하는 도구인 로그 파서 2.1이 포함되어 있습니다. 리소스 키트는 Microsoft Windows XP 및 Microsoft®® Windows® Server™ 2003에 설치할 수 있습니다.
성능 데이터를 수집하고, 이벤트 로그를 필터링하고, Microsoft® SQL Server 데이터베이스에 주요 데이터를 기록하는 애플리케이션을 작성할 수도 있습니다. System.Diagnostics 네임스페이스를 사용하여 이 작업을 수행하는 것은 놀랍도록 쉽습니다. System.Diagnostics.Process 클래스를 사용하여 작업자 프로세스 다시 시작을 모니터링할 수도 있습니다.
시작하는 데 도움이 되도록 이 문서의 맨 위에 있는 링크를 사용하여 몇 가지 유용한 도구에 대한 샘플 코드를 다운로드합니다.
- 프로세스에 대한 성능 데이터를 로깅하기 위한 명령줄 도구인 snap.exe 소스 코드입니다. Snap.cs 파일에는 간단한 설명이 포함되어 있으며 도구를 컴파일하는 방법을 설명합니다.
- HTTP 요청에 대한 TTLB(Time to Last byte)를 기록하는 간단한 클라이언트인 HttpClient.exe 소스 코드입니다. HttpClient.cs 파일에는 간단한 설명이 포함되어 있으며 도구를 컴파일하는 방법을 설명합니다.
- ASP.NET 애플리케이션을 스트레스 테스트하기 위한 명령줄 도구인 qqq.exe 소스 코드입니다. ACT(Microsoft® Application Center Test)와 같은 스트레스 클라이언트와 함께 사용하는 경우 이 도구는 디버거를 작업자 프로세스에 연결하고 특정 성능 카운터를 모니터링합니다. 성능이 저하될 때 디버거에 침입하도록 튜닝할 수 있습니다. qqq.cs 파일에는 breif 설명이 포함되어 있으며 도구를 컴파일하는 방법을 설명합니다.
- pminfo.aspx 페이지는 System.Web.ProcessModelInfo 클래스를 사용하여 aspnet_wp 프로세스 다시 시작에 대한 정보를 표시합니다. w3svc 서비스가 중지될 때까지 기록이 유지됩니다.
- ErrorHandler.dll 소스 코드입니다. 처리되지 않은 예외를 이벤트 로그에 기록하기 위해 HTTP 파이프라인에 추가할 수 있는 IHttpModule입니다. SQL Server 데이터베이스에 오류를 기록하는 것이 좋지만 간단히 하기 위해 이벤트 로그를 사용하는 예제입니다.
또 다른 간단한 단계는 Application_Error 구현하는 것입니다. global.asax에 다음 텍스트를 추가하고 처리되지 않은 대부분의 오류를 애플리케이션 로그에 즉시 로깅하기 시작할 수 있습니다.
<%@ import namespace="System.Diagnostics" %> <%@ import namespace="System.Text" %> const string sourceName = ".NET Runtime"; const string serverName = "."; const string logName = "Application"; const string uriFormat = "\r\n\r\nURI: {0}\r\n\r\n"; const string exceptionFormat = "{0}: \"{1}\"\r\n{2}\r\n\r\n"; void Application_Error(Object sender, EventArgs ea) { StringBuilder message = new StringBuilder(); if (Request != null) { message.AppendFormat(uriFormat, Request.Path); } if (Server != null) { Exception e; for (e = Server.GetLastError(); e != null; e = e.InnerException) { message.AppendFormat(exceptionFormat, e.GetType().Name, e.Message, e.StackTrace); } } if (!EventLog.SourceExists(sourceName)) { EventLog.CreateEventSource(sourceName, logName); } EventLog Log = new EventLog(logName, serverName, sourceName); Log.WriteEntry(message.ToString(), EventLogEntryType.Error); //Server.ClearError(); // uncomment this to cancel the error }
Application_Error 페이지 내에서 파서, 컴파일 및 런타임 오류를 catch합니다. 구성 문제는 catch하지 않으며, aspnet_isapi 요청을 처리하는 동안 inetinfo 내에서 발생하는 오류를 catch하지도 않습니다. 또한 가장을 사용하는 경우 가장된 토큰에는 이 이벤트 원본에 쓸 수 있는 권한이 있어야 합니다. SQL Server 데이터베이스에 오류를 로깅하여 가장 문제를 방지할 수 있습니다.
마지막으로 Windows용 Microsoft® 디버깅 도구는 프로덕션 웹 서버에서 문제를 디버깅하는 데 매우 유용합니다. 이러한 도구는 에서 https://www.microsoft.com/whdc/ddk/debugging/installx86.mspx다운로드할 수 있습니다. 디버거 windbg.exe 로드하거나 관리 코드를 디버그하기 위해 cdb.exe 수 있는 sos.dll 라는 디버거 확장이 있습니다. GC(가비지 수집) 힙의 콘텐츠를 덤프하고, 관리되는 스택 추적을 표시하고, 관리되는 잠금에 대한 경합 조사를 지원하며, 스레드 풀 통계를 표시할 수 있습니다. 이는 .NET Framework 애플리케이션용 프로덕션 디버깅에 언급된 디버깅 도구 집합의 일부로 다운로드할 수 있습니다.
성능 카운터 이해
다음은 중요한 성능 카운터 및 사용 방법에 대한 간략한 설명입니다.
.NET CLR 예외 카운터
모든 관리되는 프로세스에서 업데이트되므로 _Global_ 카운터 instance 이 카운터와 함께 사용하면 안 됩니다. 대신 aspnet_wp instance 사용합니다.
#Exceps throw / 초. 초당 throw된 관리되는 예외의 총 수입니다. 이 숫자가 증가하면 성능이 저하됩니다. 예외는 일반 처리의 일부로 throw되어서는 안 됩니다. 그러나 Response.Redirect, Server.Transfer 및 Response.End 는 모두 ThreadAbortException 이 여러 번 throw되고 이러한 메서드에 크게 의존하는 사이트에서 성능이 저하됩니다. Response.Redirect를 사용해야 하는 경우 Response.End를 호출하지 않으므로 throw되지 않는 Response.Redirect(url, false)를 호출합니다. 단점은 Response.Redirect(url, false) 에 대한 호출을 따르는 사용자 코드가 실행된다는 것입니다. 정적 HTML 페이지를 사용하여 리디렉션할 수도 있습니다. Microsoft 기술 자료 문서 312629 자세한 내용을 제공합니다.
이 매우 유용한 성능 카운터를 모니터링하는 것 외에도 관리자에게 문제를 알리기 위해 Application_Error 이벤트를 사용해야 합니다.
임계값: RPS의 5% 이 값보다 큰 값을 조사해야 하며 필요에 따라 새 임계값을 설정해야 합니다.
.NET CLR 로드 카운터
모든 관리되는 프로세스에서 업데이트되므로 _Global_ 카운터 instance 이러한 성능 카운터와 함께 사용하면 안 됩니다. 대신 aspnet_wp instance 사용합니다.
현재 AppDomains. 프로세스에 로드된 AppDomain의 현재 수입니다. 이 카운터의 값은 웹 애플리케이션 수와 1을 더한 값이어야 합니다. 추가 AppDomain은 기본 도메인입니다.
현재 어셈블리. 프로세스에 로드된 어셈블리의 현재 수입니다. 기본적으로 디렉터리의 ASPX 및 ASCX 파일은 "일괄 처리"로 컴파일됩니다. 일반적으로 종속성에 따라 1~3개의 어셈블리가 생성됩니다. 예를 들어 ASCX 파일에 구문 분석 시간 종속성이 있는 ASPX 페이지가 있는 경우 일반적으로 두 어셈블리가 생성됩니다. 하나는 ASPX 파일, 다른 ASCX 파일을 포함합니다. 구문 분석 시간 종속성에는 %@ 가져오기 %, %@ 참조 %, <%@ 레지스터 %>> 지시문에서 <만든 종속성이 포함됩니다.<> LoadControl 메서드를 통해 로드된 컨트롤은 구문 분석 시간 종속성을 만들지 않습니다. global.asax는 단독으로 어셈블리로 컴파일됩니다.
경우에 따라 과도한 메모리 사용은 비정상적으로 많은 수의 로드된 어셈블리로 인해 발생합니다. 예를 들어 뉴스 기사를 표시하는 사이트는 각 아티클에 사용된 단일 ASPX 파일보다 데이터베이스에서 뉴스를 가져오는 작은 ASPX 파일 집합을 사용하여 성능이 향상됩니다. 사이트 디자이너는 콘텐츠를 동적으로 생성하고, 캐싱을 사용하고, ASPX 및 ASCX 페이지 수를 줄여야 합니다.
AppDomain에서 어셈블리를 언로드할 수 없습니다. 과도한 메모리 사용을 방지하기 위해 재 컴파일 수(ASPX, ASCX, ASAX)가 numRecompilesBeforeAppRestart=/>컴파일로 지정된 <제한을 초과하면 AppDomain이 언로드됩니다. <%@ 페이지 debug=%> 특성이 true로 설정되거나 컴파일 debug=/>가 true로 설정된 경우 <일괄 처리 컴파일이 비활성화됩니다.
로더 힙의 바이트입니다. 모든 AppDomains에서 클래스 로더가 커밋한 바이트 수입니다. 이 카운터는 안정적인 상태에 도달해야 합니다. 이 카운터가 지속적으로 증가하는 경우 "현재 어셈블리" 카운터를 모니터링합니다. AppDomain당 로드된 어셈블리가 너무 많을 수 있습니다.
.NET CLR 메모리 카운터
모든 관리되는 프로세스에서 업데이트되므로 _Global_ 카운터 instance 이러한 성능 카운터와 함께 사용하면 안 됩니다. 대신 aspnet_wp instance 사용합니다.
모든 힙의 바이트 수입니다. 관리되는 개체에서 커밋한 바이트 수입니다. 이는 큰 개체 힙과 0세대, 1, 2세대 힙의 합계입니다. 이러한 메모리 영역은 MEM_COMMIT 형식입니다( VirtualAlloc에 대한 플랫폼 SDK 설명서 참조). 이 카운터의 값은 프로세스의 모든 MEM_COMMIT 지역을 계산하는 Process\Private Bytes 값보다 항상 작습니다. 모든 힙의 프라이빗 바이트에서 # 바이트를 뺀 값은 관리되지 않는 개체에서 커밋한 바이트 수입니다. 과도한 메모리 사용량 조사의 첫 번째 단계는 관리되는 개체 또는 관리되지 않는 개체에서 사용 중인지 여부를 확인하는 것입니다.
과도한 관리되는 메모리 사용을 조사하려면 .NET Framework 애플리케이션에 대한 프로덕션 디버깅에서 읽을 수 있는 WINDBG.EXE 및 SOS.DLL 것이 좋습니다. SOS.DLL 관리되는 힙의 개체 수, 크기 및 유형을 나열하는 "!dumpheap –stat" 명령이 있습니다. "!dumpheap –mt"를 사용하여 개체의 주소를 가져오고 "!gcroot"를 사용하여 해당 루트를 볼 수 있습니다. "!eeheap" 명령은 관리되는 힙에 대한 메모리 사용 통계를 제공합니다.
메모리 사용량을 진단하는 데 유용한 또 다른 도구는 아래에 자세히 설명된 CLR Profiler입니다.
일반적으로 다음과 같은 경우에 관리되는 메모리 사용량이 크게 증가합니다.
- 큰 데이터 집합을 메모리에 읽어들이는 경우
- 과도한 캐시 엔트리를 만드는 경우
- 큰 파일을 업로드하거나 다운로드하는 경우
- 파일을 구문 분석할 때 정규식이나 문자열을 지나치게 많이 사용하는 경우
- 과도한 ViewState.
- 세션 상태에 데이터가 너무 많거나 세션이 너무 많은 경우
# Gen 0 컬렉션. 0세대 개체가 가비지 수집된 횟수입니다. 살아남은 개체는 1세대로 승격됩니다. 컬렉션은 개체를 할당하기 위해 공간이 필요하거나 누군가가 System.GC.Collect를 호출하여 컬렉션을 강제 적용할 때 수행됩니다. 더 높은 세대를 포함하는 컬렉션은 하위 세대의 컬렉션 앞에 있기 때문에 더 오래 걸립니다. 2세대 컬렉션의 백분율을 최소화하려고 시도합니다. 일반적으로 0세대 컬렉션의 수는 1세대 컬렉션 수보다 10배 더 크고, 마찬가지로 1세대와 2세대의 경우 10배 더 커야 합니다. # Gen N 컬렉션 카운터 및 GC 카운터의 % 시간은 과도한 할당으로 인한 성능 문제를 식별하는 데 가장 적합합니다. 성능 향상을 위해 수행할 수 있는 단계는 GC의 %Time에 대한 설명을 참조하세요.
# Gen 1 컬렉션. 1세대 개체가 가비지 수집된 횟수입니다. 살아남은 개체는 2세대로 승격됩니다.
임계값: # Gen 0 컬렉션 값의 1/10입니다. 성능이 좋은 애플리케이션은 # Gen 0 컬렉션 카운터에 대한 설명에 언급된 thumb 규칙을 따릅니다.
# Gen 2 컬렉션. 2세대 개체가 가비지 수집된 횟수입니다. 2세대는 가장 높기 때문에 컬렉션에서 살아남는 개체는 2세대에 남아 있습니다. Gen 2 컬렉션은 특히 Gen 2 힙의 크기가 과도한 경우 비용이 많이 들 수 있습니다.
임계값: # Gen 1 컬렉션 값의 1/10입니다. 성능이 좋은 애플리케이션은 # Gen 0 컬렉션 카운터에 대한 설명에 언급된 thumb 규칙을 따릅니다.
% Time in GC. 마지막 가비지 수집을 수행하는 데 소요된 시간의 백분율입니다. 평균 값이 5% 이하인 경우 정상으로 간주되지만 이보다 큰 급증은 드문 일이 아닙니다. 모든 스레드는 가비지 수집 중에 일시 중단됩니다.
GC에서 높은 % 시간의 가장 일반적인 원인은 요청별로 너무 많은 할당을 만드는 것입니다. 두 번째로 일반적인 원인은 대량의 데이터를 ASP.NET 캐시에 삽입하고, 제거하고, 다시 생성하고, 몇 분마다 캐시에 다시 삽입하는 것입니다. 할당을 크게 줄이기 위해 수행할 수 있는 작은 변경이 있는 경우가 많습니다. 예를 들어 연결된 문자열을 가비지 수집해야 하므로 요청별로 문자열 연결 비용이 많이 들 수 있습니다. 적절한 초기 용량을 사용하는 StringBuilder는 문자열 연결보다 성능이 우수합니다. 그러나 StringBuilder도 가비지 수집해야 하며 부적절하게 사용되는 경우 내부 버퍼의 크기가 조정됨에 따라 예상보다 많은 할당이 발생할 수 있습니다. 각 문자열에서 Response.Write 를 여러 번 호출하면 StringBuilder와 결합하는 것보다 훨씬 더 나은 성능을 발휘하므로 StringBuilder altogther를 방지할 수 있는 경우 수행하세요.
애플리케이션은 응답을 생성하는 동안 StringBuilder 또는 MemoryStream에 데이터를 일시적으로 저장하는 경우가 많습니다. 각 요청에서 이 임시 스토리지를 다시 만드는 대신 다시 사용할 수 있는 문자 또는 바이트 배열의 버퍼 풀을 분석하는 것이 좋습니다. 버퍼 풀은 GetBuffer 및 ReturnBuffer 루틴이 있는 개체입니다. GetBuffer 루틴은 버퍼의 내부 저장소에서 버퍼를 반환하려고 하지만 저장소가 비어 있으면 새 버퍼를 만듭니다. 저장된 버퍼의 최대 수에 아직 도달하지 않은 경우 ReturnBuffer 루틴은 저장소에 버퍼를 반환하지만 그렇지 않으면 해제합니다. 이 버퍼 풀 구현의 단점은 스레드 안전을 위해 잠금이 필요하다는 것입니다. 또는 HttpContext.ApplicationInstance를 사용하여 global.asax에 정의된 instance 필드에 액세스하여 잠금의 성능 영향을 방지할 수 있습니다. 각 파이프라인 instance 대해 global.asax의 instance 하나 있으므로 한 번에 하나의 요청에서만 필드에 액세스할 수 있으므로 재사용 가능한 문자 또는 바이트 버퍼를 저장할 수 있습니다.
GC에서 % 시간을 줄이려면 할당 패턴을 알아야 합니다. CLR Profiler를 사용하여 최대 몇 분 동안 단일 요청 또는 가벼운 스트레스를 프로파일합니다. (이러한 도구는 침략적이며 producton에서 사용할 수 없습니다.) 할당 그래프 보기에는 각 개체 유형에 대해 할당된 총 메모리와 할당을 수행한 호출 스택이 표시됩니다. 이를 사용하여 과도한 할당을 줄입니다. 크기별 히스토그램 보기(보기 메뉴에서 히스토그램 할당 형식 선택)에는 할당된 개체의 크기가 요약되어 있습니다. 85,000바이트보다 큰 수명이 짧은 개체를 할당하지 않습니다. 이러한 개체는 큰 개체 힙에 할당되며 수집 비용이 더 많이 듭니다. 크기별 히스토그램 보기에서 마우스로 개체를 선택하고 마우스 오른쪽 단추를 클릭하여 할당한 사람을 확인할 수 있습니다. 할당을 줄이는 것은 코드 수정 및 프로파일링의 반복적인 프로세스입니다.
임계값: 평균 5% 이하, 이보다 큰 단기 스파이크가 일반적입니다. 이 값보다 큰 평균 값을 조사해야 합니다. 필요에 따라 새 임계값을 설정해야 합니다.
ASP.NET 카운터
이 범주의 성능 카운터는 w3svc 서비스가 시작될 때만 0으로 다시 설정됩니다.
애플리케이션이 다시 시작됩니다. 애플리케이션 다시 시작 횟수입니다. 애플리케이션 도메인을 다시 만들고 페이지를 다시 컴파일하는 데 시간이 걸리므로 예기치 않은 애플리케이션 다시 시작을 조사해야 합니다. 다음 중 하나가 발생하면 애플리케이션 도메인이 언로드됩니다.
- machine.config, web.config또는 global.asax 수정
- 애플리케이션의 bin 디렉터리 또는 해당 내용을 수정합니다.
- 컴파일 수(ASPX, ASCX 또는 ASAX)가 numRecompilesBeforeAppRestart=/>컴파일에 <지정된 제한을 초과하는 경우
- 가상 디렉터리의 실제 경로를 수정합니다.
- 코드 액세스 보안 정책 수정.
- 웹 서비스가 다시 시작됩니다.
프로덕션 환경에서 웹 팜의 경우 최상의 성능과 안정성을 위해 콘텐츠를 업데이트하기 전에 서버를 순환에서 제거하는 것이 좋습니다. 프로덕션의 단일 웹 서버의 경우 서버가 로드되는 동안 콘텐츠를 업데이트할 수 있습니다. 기술 자료 문서 810281 설명된 핫픽스는 애플리케이션이 다시 시작된 후 오류가 발생하는 모든 사용자에게 관심이 있습니다. 예를 들어 "다른 프로세스에서 사용 중이므로 FileName> 파일에 <액세스할 수 없습니다."와 유사한 오류와 함께 위반을 공유합니다.
바이러스 백신 소프트웨어 및 애플리케이션 다시 시작과 관련된 문제는 기술 자료 문서 820746 수정 : 수정: 일부 바이러스 백신 프로그램으로 인해 v1.0에 대해 웹 애플리케이션이 예기치 않게 다시 시작 되고 기술 자료 문서에서 v1.1에 대한 기술 자료 문서 821438 해결되었습니다.
임계값: 0. 완벽한 환경에서 애플리케이션 도메인은 프로세스의 수명 동안 유지됩니다. 과도한 값을 조사해야 하며 필요에 따라 새 임계값을 설정해야 합니다.
실행 중인 애플리케이션. 실행 중인 애플리케이션의 수입니다.
요청 현재. ASP.NET ISAPI에서 현재 처리되는 요청 수입니다. 여기에는 큐에 대기 중이거나 실행 중이거나 클라이언트에 기록되기를 기다리는 항목이 포함됩니다. 이 성능 카운터는 기술 자료 문서 329959 설명된 SP3 이전 핫픽스의 ASP.NET v1.0에 추가되었습니다.
ASP.NET 이 카운터가 processModel 구성 섹션에 정의된 requestQueueLimit를 초과하면 요청을 거부하기 시작합니다. requestQueueLimit는 aspnet_wp 실행할 때 IIS 5.0의 ASP.NET 적용되지만 놀랍게도 w3wp에서 실행할 때 IIS 6.0에도 적용됩니다. IIS 6.0에서 실행할 때 여러 processModel 구성 설정이 계속 적용된다는 것은 잘 알려져 있지 않습니다. 여기에는 requestQueueLimit, responseDeadlockInterval, maxWorkerThreads, maxIoThreads, minWorkerThreads 및 minIoThreads가 포함됩니다. ASP.NET 2003년 6월 1.1일 핫픽스 롤업 패키지에서 수정된 프레임워크의 v1.1 버그를 통해 ASP.NET IIS 6.0에서 실행할 때 무한 수의 요청을 처리할 수 있습니다. 수정으로 인해 ASP.NET Requests Current가 requestQueueLimit를 초과할 때 요청을 거부합니다.
클래식 ASP 애플리케이션의 경우 큐에 대기된 요청은 요청이 거부되는 시기에 대한 경고를 제공합니다. ASP.NET 경우 현재 요청과 애플리케이션 큐의 요청이 함께 이 기능을 제공합니다. 이 카운터는 ASP.NET 교착 상태 검색 메커니즘에서도 사용됩니다. Requests Current가 0보다 크고 processModel responseDeadlockInterval=/>에 지정된 < 제한보다 큰 기간 동안 작업자 프로세스에서 응답을 받지 못한 경우 프로세스가 종료되고 새 프로세스가 시작됩니다. 기술 자료 문서 328267 설명된 SP3 이전 핫픽스에서 요청 현재가 processModel/> 구성 섹션에 지정된 maxWorkerThreads 및 maxIoThreads의 합계보다 커야 하므로 알고리즘이 수정되었습니다<. 기본적으로 요청 실행 시간 제한은 90초이며 의도적으로 responseDeadlockInterval보다 작습니다. 요청 실행 시간 제한은 httpRuntime executionTimeout=/> 구성 설정 또는 Server.ScriptTimeout 속성을 통해 < 수정할 수 있지만 항상 responseDeadlockInterval보다 작아야 합니다.
요청 실행 시간. 마지막 요청을 실행하는 데 걸린 시간(밀리초)입니다. Framework 버전 1.0에서는 작업자 프로세스가 요청을 수신할 때 실행 시간이 시작되고 ASP.NET ISAPI가 IIS에 HSE_REQ_DONE_WITH_SESSION 보낼 때 중지됩니다. IIS 버전 5의 경우 클라이언트에 응답을 쓰는 데 걸린 시간이 포함되지만 IIS 버전 6의 경우 응답 버퍼가 비동기적으로 전송되므로 클라이언트에 응답을 작성하는 데 걸리는 시간은 포함되지 않습니다. 따라서 IIS 버전 5에서 네트워크 연결이 느린 클라이언트는 이 카운터의 값을 상당히 증가합니다.
Framework 버전 1.1에서는 요청에 대한 HttpContext가 만들어질 때 실행 시간이 시작되고 응답이 IIS로 전송되기 전에 중지됩니다. 사용자 코드가 HttpResponse.Flush를 호출하지 않는다고 가정하면 IIS 또는 클라이언트에 바이트를 보내기 전에 실행 시간이 중지됩니다.
ASP.NET\요청 실행 시간은 instance 카운터이며 매우 휘발성입니다. 반면에 TTLB(Time to Last Byte)는 쉽게 평균화되고 일정 기간 동안 더 나은 성능 추정치를 계산하는 데 사용할 수 있습니다. TTLB는 관리 코드로 작성된 간단한 HTTP 클라이언트를 통해 계산하거나 ACT(Application Center Test)와 같이 TTLB를 계산하는 데 사용할 수 있는 많은 HTTP 클라이언트 중 하나를 사용할 수 있습니다.
compilation debug=/>가 TRUE로 설정된 경우 < 일괄 처리 컴파일이 비활성화되고 <httpRuntime executionTimeout=/> 구성 설정과 Server.ScriptTimeout에 대한 호출은 무시됩니다. 디버그 페이지에 대한 요청은 이론적으로 영원히 실행될 수 있으므로 processModel responseDeadlockInterval=/> 설정이 Infinite로 설정되지 않은 경우 < 문제가 발생할 수 있습니다.
임계값: N.A. 이 카운터의 값은 안정적이어야 합니다. 환경은 특정 사이트에 대한 임계값을 설정하는 데 도움이 됩니다. 프로세스 모델을 사용하도록 설정하면 요청 실행 시간에는 클라이언트에 응답을 작성하는 데 필요한 시간이 포함되므로 클라이언트 연결의 대역폭에 따라 달라집니다.
큐에 대기된 요청입니다. 현재 큐에 대기 중인 요청 수입니다. IIS 5.0에서 실행하는 경우 inetinfo와 aspnet_wp 사이에 큐가 있고 각 가상 디렉터리에 대해 하나의 큐가 있습니다. IIS 6.0에서 실행하는 경우 네이티브 코드에서 관리되는 ThreadPool에 요청이 게시되는 큐와 각 가상 디렉터리에 대한 큐가 있습니다. 이 카운터에는 모든 큐의 요청이 포함됩니다. inetinfo와 aspnet_wp 사이의 큐는 요청이 한 프로세스에서 다른 프로세스로 전송되는 명명된 파이프입니다. aspnet_wp 프로세스에서 사용 가능한 I/O 스레드가 부족하면 이 큐의 요청 수가 증가합니다. IIS 6.0에서는 들어오는 요청이 있고 작업자 스레드가 부족할 때 증가합니다.
요청 현재 카운터가 processModel requestQueueLimit=/>를 초과하면< 요청이 거부됩니다. 많은 사람들이 요청 대기 중 카운터가 requestQueueLimit를 초과할 때 발생하지만 그렇지 않다고 생각합니다. 이 제한을 초과하면 503 상태 코드와 "서버가 너무 사용 중입니다."라는 메시지와 함께 요청이 거부됩니다. 이러한 이유로 요청이 거부되면 관리 코드에 도달하지 않으며 오류 처리기에는 알림이 표시되지 않습니다. 일반적으로 이는 서버의 부하가 매우 많은 경우에만 문제가 되지만 매시간 "버스트" 로드로 인해 이 문제가 발생할 수도 있습니다. 비정상적인 버스트 로드 시나리오의 경우 기술 자료 문서 810259 설명된 핫픽스에 관심이 있을 수 있습니다. 이를 통해 CPU당 기본값인 1에서 최소 I/O 스레드 수를 늘릴 수 있습니다.
각 가상 디렉터리에는 작업자 및 I/O 스레드의 가용성을 유지하는 데 사용하는 큐가 있습니다. 사용 가능한 작업자 스레드 또는 사용 가능한 I/O 스레드 수가 httpRuntime minFreeThreads=/>에 지정된 < 제한보다 낮으면 이 큐의 요청 수가 증가합니다. httpRuntime appRequestQueueLimit=/>로 지정된 < 제한을 초과하면 요청이 503 상태 코드로 거부되고 클라이언트는 "서버가 너무 사용 중"이라는 메시지와 함께 HttpException을 받습니다.
그 자체로 이 카운터는 성능 문제에 대한 명확한 지표가 아니며 요청이 거부되는 시기를 결정하는 데 사용할 수도 없습니다. 기술 자료 문서 329959 이 문제를 해결하기 위해 두 개의 새로운 성능 카운터인 현재 요청 및 애플리케이션 큐의 요청이 도입되었습니다. 이 두 카운터에 대한 설명과 거부된 요청을 참조하세요.
요청이 거부되었습니다. 거부된 요청의 수입니다. 큐 제한 중 하나가 초과되면 요청이 거부됩니다(대기 중인 요청 설명 참조). 요청은 여러 가지 이유로 거부될 수 있습니다. 느린 SQL 서버로 인한 백 엔드 대기 시간은 종종 파이프라인 인스턴스 수가 급격히 증가하고 CPU 사용률 및 요청/초가 감소하기 때문입니다. 프로세서 또는 메모리 제약 조건으로 인해 부하가 많은 시간에 서버가 과부하가 발생하여 결국 요청이 거부될 수 있습니다.
애플리케이션의 디자인으로 인해 요청 실행 시간이 과도하게 발생할 수 있습니다. 예를 들어 일괄 컴파일은 페이지에 대한 첫 번째 요청이 수신될 때 디렉터리의 모든 페이지가 단일 어셈블리로 컴파일되는 기능입니다. 디렉터리에 수백 페이지가 있는 경우 이 디렉터리에 대한 첫 번째 요청을 실행하는 데 시간이 오래 걸릴 수 있습니다. compilation batchTimeout=/>를 초과하면 < 일괄 처리 컴파일은 백그라운드 스레드에서 계속되며 요청된 페이지는 개별적으로 컴파일됩니다. 일괄 처리 컴파일에 성공하면 어셈블리가 디스크에 유지되고 애플리케이션이 다시 시작된 후 다시 사용할 수 있습니다. 그러나 애플리케이션의 bin 폴더에 있는 global.asax, web.config, machine.config 또는 어셈블리가 수정되면 종속성 변경으로 인해 일괄 처리 컴파일 프로세스가 다시 실행됩니다.
대규모 사이트를 신중하게 디자인하면 성능에 큰 영향을 미칠 수 있습니다. 이 경우 쿼리 문자열 데이터에 따라 동작이 다른 페이지가 몇 페이지만 있는 것이 좋습니다. 일반적으로 웹 사이트에서 하나 이상의 페이지를 요청하는 HTTP 클라이언트를 사용하여 TTLB(마지막 바이트까지의 평균 시간)로 가장 잘 모니터링되는 요청 실행 시간을 최소화해야 합니다.
다음 성능 카운터는 거부된 요청의 원인을 검색하는 데 가장 적합합니다.
- Process\% Processor Time
- Process\Private Bytes
- Process\Thread Count
- Web Service\ISAPI Extension Requests/sec
- ASP.NET\Requests Current
- ASP.NET\큐에 대기된 요청
- ASP.NET\요청 대기 시간
- ASP.NET Applications\Pipeline Instance Count
- 애플리케이션 큐에서 애플리케이션\요청 ASP.NET
임계값: 0. 이 카운터의 값은 0이어야 합니다. 이 값보다 큰 값을 조사해야 합니다.
요청 대기 시간. inetinfo와 aspnet_wp 사이에 존재하는 큐 또는 명명된 파이프에서 대기하는 데 가장 최근 요청이 소요된 시간(밀리초)입니다(대기 중인 요청 설명 참조). 애플리케이션 큐에서 대기하는 데 소요된 시간은 포함되지 않습니다.
임계값: 1000. 평균 요청은 큐에서 대기하는 데 0밀리초를 소비해야 합니다.
작업자 프로세스 실행 중. 현재 aspnet_wp 작업자 프로세스 수입니다. 짧은 기간 동안 새 작업자 프로세스와 교체되는 작업자 프로세스가 공존할 수 있습니다. 드물긴 하지만 종료하는 동안 교착 상태를 처리하는 경우도 있습니다. 의심스러운 경우 도구를 사용하여 작업자 프로세스의 인스턴스 수를 모니터링하는 것이 좋습니다. 또는 이러한 중단 프로세스는 메모리를 사용하므로 Memory\Available Mbytes 성능 카운터를 사용할 수 있습니다.
임계값: 2. 이전 작업자 프로세스를 종료하는 동안 두 개의 인스턴스가 있을 수 있습니다. webGarden을 사용하는 경우 임계값은 #CPUs 더하기 1이어야 합니다. 이보다 큰 값은 매우 짧은 기간 내에 과도한 프로세스가 다시 시작되었음을 나타낼 수 있습니다.
작업자 프로세스가 다시 시작됩니다. aspnet_wp 프로세스 다시 시작 횟수입니다.
임계값: 1. 프로세스 다시 시작은 비용이 많이 들고 바람직하지 않습니다. 값은 프로세스 모델 구성 설정뿐만 아니라 예기치 않은 액세스 위반, 메모리 누수 및 교착 상태에 따라 달라집니다. aspnet_wp 다시 시작되면 애플리케이션 이벤트 로그 항목에 그 이유가 표시됩니다. 액세스 위반 또는 교착 상태가 발생하면 요청이 손실됩니다. 프로세스 모델 설정을 사용하여 프로세스를 선제적으로 재활용하는 경우 적절한 임계값을 설정해야 합니다.
ASP.NET 애플리케이션 카운터
이 범주의 성능 카운터는 애플리케이션 도메인 또는 웹 서비스를 다시 시작할 때 0으로 다시 설정됩니다.
총 항목을 캐시합니다. 캐시의 현재 항목 수(사용자 및 내부 모두)입니다. 내부적으로 ASP.NET 캐시를 사용하여 구성 개체, 유지된 어셈블리 항목, MapPath 메서드에서 매핑된 경로 및 In-Process 세션 상태 개체를 포함하여 만드는 데 비용이 많이 드는 개체를 저장합니다.
참고 성능 카운터의 "캐시 합계" 제품군은 In-process 세션 상태 문제를 진단하는 데 유용합니다. 캐시에 너무 많은 개체를 저장하는 것은 종종 메모리 누수의 원인입니다.
캐시 총 적중률입니다. 모든 캐시 요청(사용자 및 내부 모두)의 총 적중 횟수 대 누락 비율입니다.
캐시 총 이직률입니다. 초당 캐시에 대한 추가 및 제거 횟수(사용자 및 내부 모두)입니다. 높은 이직률은 항목이 빠르게 추가되고 제거되고 있음을 나타내며 비용이 많이 들 수 있습니다.
캐시 API 항목. 현재 사용자 캐시에 있는 항목 수입니다.
캐시 API 적중률입니다. 사용자 캐시 요청의 총 적중 횟수 비율입니다.
캐시 API 이직률입니다. 초당 사용자 캐시에 대한 추가 및 제거 횟수입니다. 높은 이직률은 항목이 빠르게 추가되고 제거되고 있음을 나타내며 비용이 많이 들 수 있습니다.
출력 캐시 항목. 현재 출력 캐시에 있는 항목 수입니다.
출력 캐시 적중률입니다. 출력 캐시 요청의 총 적중 대 누락 비율입니다.
출력 캐시 이직률입니다. 초당 출력 캐시에 대한 추가 및 제거 횟수입니다. 높은 이직률은 항목이 빠르게 추가되고 제거되고 있음을 나타내며 비용이 많이 들 수 있습니다.
파이프라인 인스턴스 수입니다. 활성 파이프라인 인스턴스 수입니다. 파이프라인 instance 내에서 실행 스레드를 하나만 실행할 수 있으므로 이 숫자는 지정된 애플리케이션에 대해 처리되는 최대 동시 요청 수를 제공합니다. 파이프라인 인스턴스 수는 안정적이어야 합니다. 급격한 증가는 백 엔드 대기 시간을 나타냅니다(위에서 거부된 요청에 대한 설명 참조).
컴파일 합계입니다. 컴파일된 ASAX, ASCX, ASHX, ASPX 또는 ASMX 파일의 수입니다. 생성된 어셈블리 수가 아니라 컴파일된 파일 수입니다. 어셈블리는 디스크에 보존되고 파일 종속성의 생성 시간, 마지막 쓰기 시간 또는 길이가 변경될 때까지 재사용됩니다. ASPX 페이지의 종속성에는 global.asax, web.config, machine.config, bin 폴더의 종속 어셈블리 및 페이지에서 참조하는 ASCX 파일이 포함됩니다. 파일 종속성을 수정하지 않고 애플리케이션을 다시 시작하면 컴파일 없이 보존된 어셈블리가 다시 로드됩니다. 이 성능 카운터는 파일이 처음에 구문 분석되어 어셈블리로 컴파일될 때만 증가합니다.
기본적으로 일괄 처리 컴파일을 사용하도록 설정되지만 이 카운터는 생성된 어셈블리 수에 관계없이 어셈블리로 구문 분석되고 컴파일되는 각 파일에 대해 한 번 증가합니다.
컴파일에 실패하면 카운터가 증가하지 않습니다.
전처리 중 오류입니다. 구성 및 구문 분석 오류의 총 수입니다. 이 카운터는 구성 오류 또는 구문 분석 오류가 발생할 때마다 증가합니다. 구성 오류가 캐시되더라도 오류가 발생할 때마다 카운터가 증가합니다.
참고 서버가 정상인지 여부를 확인하기 위해 "오류" 성능 카운터에만 의존하지 마세요. AppDomain이 언로드되면 0으로 다시 설정됩니다. 그러나 특정 문제를 자세히 살펴보는 데 사용할 수 있습니다. 일반적으로 관리자에게 문제를 알리기 위해 Application_Error 이벤트를 사용합니다.
컴파일 중 오류입니다. 컴파일 오류의 총 수입니다. 응답은 캐시되고 이 카운터는 파일 변경으로 인해 다시 컴파일이 강제될 때까지 한 번만 증가합니다. 이벤트를 발생시키는 사용자 지정 오류 처리를 구현합니다.
실행 중 오류입니다. 총 런타임 오류 수입니다.
실행 중에 처리되지 않은 오류입니다. 런타임에 처리되지 않은 총 예외 수입니다. 여기에는 다음이 포함되지 않습니다.
- 이벤트 처리기에서 지워진 오류(예: Page_Error 또는 Application_Error).
- 리디렉션 페이지에서 처리되는 오류입니다.
- try/catch 블록 내에서 발생하는 오류입니다.
실행 중 처리되지 않은 오류 수/초 런타임에 처리되지 않은 초당 총 예외 수입니다.
오류 합계입니다. 전처리 중 오류, 컴파일 중 오류 및 실행 중 오류의 합계입니다.
Errors Total/sec. 전처리 중 오류, 컴파일 중 오류 및 초당 실행 중 오류의 총 수입니다.
요청 실행. 현재 실행 중인 요청 수입니다. 이 카운터는 HttpRuntime 이 요청을 처리하기 시작하고 HttpRuntime 이 요청을 완료한 후 감소할 때 증가합니다. 프레임워크의 v1.1에는 2003년 6월 ASP.NET 1.1 핫픽스 롤업 패키지에서 수정된 이 성능 카운터에 버그가 있습니다. 안타깝게도 이 버그는 기술 자료 문서에 설명되어 있지 않습니다. 수정하기 전에 카운터에는 클라이언트에 응답을 작성하는 데 걸린 시간이 포함되었습니다.
애플리케이션 큐의 요청입니다. 애플리케이션 요청 큐의 요청 수입니다(위의 큐에 대기된 요청에 대한 설명 참조). 현재 요청 외에도 애플리케이션 큐의 요청은 요청이 거부되는 시기에 대한 경고를 제공합니다. 가상 디렉터리가 몇 개만 있는 경우 기본 appRequestQueueLimit 를 200 또는 300으로 늘리는 것이 적합할 수 있습니다. 특히 부하가 많은 느린 애플리케이션에 적합할 수 있습니다.
요청을 찾을 수 없습니다. 찾을 수 없는 리소스에 대한 요청 수입니다.
권한이 없는 요청입니다. 무단 액세스로 인해 요청 수가 실패했습니다.
요청 시간이 초과되었습니다. 시간이 초과된 요청 수입니다.
요청이 성공했습니다. 성공적으로 실행된 요청 수입니다.
요청 합계입니다. 애플리케이션이 시작된 이후의 요청 수입니다.
Requests/Sec. 초당 실행된 요청 수입니다. 애플리케이션 다시 시작의 영향을 받지 않으므로 "Web Service\ISAPI 확장 요청/초"를 선호합니다.
프로세스 카운터
이러한 카운터를 사용하면 관심 있는 프로세스가 aspnet_wp inetinfo입니다.
% 프로세서 시간. 이 프로세스의 스레드가 프로세서를 사용하는 데 소요되는 시간의 백분율입니다.
임계값: 70%. 오랜 기간 동안 이 값보다 큰 값은 하드웨어를 구입하거나 애플리케이션을 최적화해야 함을 나타냅니다.
핸들 개수입니다.
임계값: 10000. aspnet_wp 2,000개의 핸들 수는 의심스럽고 10,000개는 허용 가능한 한도를 훨씬 초과합니다. 모든 프로세스에 대한 총 핸들 수가 약 40,000을 초과하면 눈에 띄는 성능 저하가 발생하며, 이는 IIS에 대한 서비스 거부 공격 중에 완전히 달성할 수 있습니다.
프라이빗 바이트. 이 프로세스에서 소유한 커밋된 메모리의 현재 크기(바이트)입니다. 메모리 누수는 프라이빗 바이트의 일관되고 장기간 증가로 식별됩니다. 메모리 누수 감지에 가장 적합한 성능 카운터입니다.
IIS 5.0에서 <실행하는 경우 processModel memoryLimit=/> 구성 섹션에서 프라이빗 바이트에 대한 메모리 제한을 설정해야 합니다. IIS 6.0에서 실행하는 경우 IIS 관리자에서 메모리 제한을 설정해야 합니다. 애플리케이션 풀의 속성을 열고 재활용 탭에서 사용된 최대 메모리(MB)에 대한 제한을 지정합니다. 이 제한은 프라이빗 바이트에 해당합니다. 작업자 프로세스의 프라이빗 바이트는 메모리 제한과 비교하여 프로세스를 재활용할 시기를 결정합니다. 또한 System.Web.Caching.Cache 는 프라이빗 바이트 및 메모리 제한을 사용하여 캐시에서 항목을 삭제할 시기를 결정하므로 프로세스 재활용을 방지합니다. 특히 과도한 메모리 사용으로 인해 새 프로세스가 이전 프로세스를 대체하는 경우 페이징을 방지하기 위해 실제 RAM의 60%에 대한 메모리 제한이 권장됩니다. 기술 자료 문서 330469 실행 중인 프로세스가 많은 서버에서 프라이빗 바이트를 모니터링하지 못하는 ASP.NET 문제를 해결합니다. 또한 이 핫픽스를 사용하면 많은 수의 실행 중인 프로세스가 있을 때 캐시 메모리 관리자가 제대로 작동할 수 있습니다.
캐시 메모리 관리자 및 프로세스 재활용 기능이 제대로 작동하도록 많은 양의 실제 RAM이 있는 컴퓨터의 메모리 제한을 조정하는 것이 중요합니다. 예를 들어 기본 메모리 제한을 사용하는 실제 RAM이 4GB(기가바이트)인 서버가 있다고 가정합니다. 이것은 문제입니다. 실제 RAM의 60%는 2.4GB이며 기본 가상 주소 공간인 2GB보다 큽니다. 그렇다면 메모리 제한은 어떻게 설정되어야 할까요?
고려해야 할 몇 가지 사항이 있습니다. 첫째, "Process\Virtual Bytes"가 가상 주소 공간 제한(일반적으로 2GB)의 600MB 내에 있을 때 OutOfMemoryException 이 발생할 가능성이 크게 증가하기 시작하고, 둘째, 테스트에서는 "Process\Virtual Bytes"가 "Process\Private Bytes"보다 600MB 이하인 것으로 나타났습니다. 이러한 차이는 GC에서 유지 관리하는 MEM_RESERVE 영역으로 인해 부분적으로 발생하므로 필요할 때 더 많은 메모리를 신속하게 커밋할 수 있습니다. 이를 종합하면 "Process\Private Bytes"가 800MB를 초과하면 OutOfMemoryException 이 발생할 가능성이 높아집니다. 이 예제에서 컴퓨터에는 4GB의 실제 RAM이 있으므로 메모리 부족 상태를 방지하려면 메모리 제한을 20%로 설정해야 합니다. 이러한 숫자를 실험하여 컴퓨터의 메모리 사용량을 최대화할 수 있지만 안전하게 재생하려면 예제의 숫자가 작동합니다.
요약하자면 메모리 제한을 실제 RAM의 60% 또는 800MB로 설정합니다. v1.1은 3GB 가상 주소 공간을 지원하므로 boot.ini /3GB를 추가하면 800MB 대신 1,800MB를 상한으로 안전하게 사용할 수 있습니다.
테스트를 실행할 때 GC를 강제로 적용하고 관리되는 메모리를 안정화하려면 System.GC.GetTotalMemory(true) 를 한 번 호출할 수 있습니다. 이 메서드는 GC를 호출합니다 . 메모리가 5% 이내에 안정화될 때까지 WaitForPendingFinalizers() 를 반복적으로 수집합니다.
임계값: 실제 RAM의 최소 60%와 800MB입니다. 전체 실제 RAM의 60%를 초과하는 값은 특히 애플리케이션 및 프로세스를 다시 시작하는 동안 성능에 영향을 미치기 시작합니다. 가상 주소 공간 제한이 2GB인 프로세스에서 프라이빗 바이트가 800MB를 초과하면 OutOfMemoryException의 가용성이 크게 증가합니다.
스레드 수입니다. 이 프로세스에서 활성 상태인 스레드 수입니다. 스레드 수는 종종 부하가 너무 높을 때 증가합니다.
임계값: 75 + ((maxWorkerThread + maxIoThreads) * #CPUs). aspcompat 모드를 사용하는 경우 임계값을 늘려야 합니다. 임계값: 75 + ((maxWorkerThread + maxIoThreads) * #CPUs * 2).
가상 바이트. 이 프로세스에 대한 가상 주소 공간의 현재 크기(바이트)입니다.
boot.ini /3GB 스위치를 사용하여 3GB 주소 공간을 사용하도록 설정하지 않는 한 사용자 모드 프로세스의 가상 주소 공간 제한은 2GB입니다. 이 제한에 접근하면 성능이 저하되며 일반적으로 프로세스 또는 시스템 크래시가 발생합니다. 2GB 또는 3GB 제한에 접근하면 주소 공간이 조각화되므로 각각 1.4 또는 2.4GB의 보수적인 임계값을 권장합니다. 여기서 문제가 발생하는 경우 System.OutOfMemoryException 이 throw되는 것을 볼 수 있으며, 이로 인해 프로세스가 중단될 수도 있고 충돌하지 않을 수도 있습니다.
IIS 6.0에서 실행하는 경우 IIS 관리자에서 가상 메모리 제한을 설정할 수 있습니다. 그러나 이를 부적절하게 설정하면 ASP.NET 문제가 발생할 수 있습니다. ASP.NET 프라이빗 바이트 제한을 초과하지 않도록 캐시에서 항목을 삭제하지만 알고리즘은 이 결정에서 프라이빗 바이트 및 프라이빗 바이트 제한을 사용합니다. 가상 바이트 또는 가상 바이트 제한을 모니터링하지 않습니다. 가상 바이트와 프라이빗 바이트의 차이는 일반적으로 600MB 이하인 경우 가상 메모리 누수 또는 조각화의 가능성이 우려되는 경우 가상 바이트 제한을 프라이빗 바이트 제한보다 큰 값 600MB로 설정할 수 있습니다. 이것이 바람직한 경우 애플리케이션 풀의 속성에 대한 재활용 탭에 있는 최대 가상 메모리(MB)에 대한 제한을 설정합니다.
프레임워크 버전 1.0은 작업자 프로세스 또는 상태 서비스에서 3GB 주소 공간을 지원하지 않습니다. 그러나 inetinfo.exe 내에서 3GB 주소 공간을 사용하도록 설정하는 지침은 기술 자료 문서 320353 참조하세요. 버전 1.1은 작업자 프로세스 및 상태 서비스에 대한 3GB 주소 공간을 완벽하게 지원합니다.
임계값: 가상 주소 공간의 크기보다 600MB 작습니다(1.4 또는 2.4GB).
프로세서 카운터
% 프로세서 시간. 모든 스레드가 프로세서를 사용하는 데 소요되는 시간의 백분율입니다.
임계값: 70%. 오랜 기간 동안 이 값보다 큰 값은 하드웨어를 구입하거나 애플리케이션을 최적화해야 함을 나타냅니다.
메모리 카운터
사용 가능한 Mbytes. 사용 가능한 실제 RAM의 양입니다.
임계값: 실제 RAM의 20%. 이 값보다 작은 값을 조사해야 하며 하드웨어를 구매해야 한다는 것을 나타낼 수 있습니다.
시스템 카운터
- Context Switches/sec. 프로세서가 스레드 컨텍스트를 전환하는 속도입니다. 숫자가 높을수록 잠금 경합이 높거나 사용자와 커널 모드 간의 전환이 발생할 수 있습니다. 컨텍스트 스위치/초는 처리량, 로드 및 CPU 수에 따라 선형적으로 증가해야 합니다. 기하급수적으로 증가하는 경우 문제가 있습니다. 프로파일러를 사용하여 추가 조사를 수행해야 합니다.
웹 서비스 카운터
- 현재 연결. 이 카운터의 임계값은 요청 유형(ISAPI, CGI, 정적 HTML 등), CPU 사용률 등과 같은 많은 변수에 따라 달라집니다. 경험을 통해 임계값을 개발해야 합니다.
- Total Method Requests/sec. 주로 성능 문제를 진단하기 위한 메트릭으로 사용됩니다. 이 값을 "ASP.NET Applications\Requests/sec" 및 "Web Service\ISAPI Extension Requests/sec"와 비교하여 aspnet_isapi.dll 렌더링된 정적 페이지와 처리되는 페이지의 백분율을 확인하는 것이 흥미로울 수 있습니다.
- ISAPI 확장 요청/초. 주로 성능 문제를 진단하기 위한 메트릭으로 사용됩니다. 이를 "ASP.NET Applications\Requests/sec" 및 "Web Service\Total Method Requests/sec"와 비교하는 것은 흥미로울 수 있습니다. 여기에는 aspnet_isapi.dll 아니라 모든 ISAPI 확장에 대한 요청이 포함됩니다.
결론
라이브로 전환하기 전에 애플리케이션의 신중한 스트레스 및 성능 테스트는 큰 골칫거리를 방지할 수 있습니다. 많은 사람들이 접하는 두 가지 주요 걸림돌이 있는 것 같습니다.
- 웹 사이트에서 경험할 것으로 예상되는 트래픽 및 로드를 시뮬레이션할 수 있는 HTTP 클라이언트를 사용해야 합니다.
- 프로덕션 환경과 거의 동일한 환경에서 전체 애플리케이션을 테스트해야 합니다.
실제 웹 사이트 트래픽을 시뮬레이션하는 것은 쉽지 않지만 문제를 경험하는 대부분의 애플리케이션은 결코 적절하게 스트레스 테스트를 받지 못했다고 솔직히 말할 수 있습니다. 이 문서는 성능 카운터를 이해하고 성능을 모니터링하는 데 유용한 도구를 만드는 데 도움이 됩니다. 부하를 적용하려면 Microsoft Visual Studio® .NET에 포함된 ACT(Microsoft® Application Center Test)를 사용하는 것이 좋습니다. 이 스트레스 도구에 대한 자세한 내용은 Microsoft Application Center Test 1.0, Visual Studio .NET Edition에서 확인할 수 있습니다. 또한 WAST(Microsoft® Web Application Stress Tool)를 사용하는 것이 좋습니다. TechNet에서 무료로 다운로드할 수 있습니다. 애플리케이션 에서 ViewState를 사용하는 경우 WAST가 응답을 동적으로 구문 분석할 수 없으므로 ACT를 사용해야 합니다.
나는 그것이 생산 환경에 대해 무엇인지 모르겠지만, 그들에 대해 특별한 무언가가 분명히 있다. "문제는 프로덕션 사이트에서만 발생합니다."라는 말을 들은 횟수를 계산할 수 없습니다. 일반적으로 차이점은 애플리케이션 자체입니다. 랩에서 시뮬레이션할 수 없는 애플리케이션의 일부가 있는 경우가 많습니다. 예를 들어 광고 서버가 테스트에서 생략되었거나 실제 데이터베이스를 시뮬레이션하는 데 사용되는 데이터베이스가 크게 다릅니다. 경우에 따라 네트워크 또는 DNS 차이가 원인이며 서버가 실행되는 하드웨어의 차이인 경우도 있습니다.
몇 년 동안 ASP.NET 애플리케이션의 성능을 디버깅하고 모니터링해왔지만 도움이 필요한 경우도 있습니다. 이 위치에 있는 경우 ASP.NET 웹 사이트의 포럼에서 답변을 찾을 수 있습니다. 하지만 실제로 바인드에 있는 경우 해당 사이트에 제공된 연락처 정보를 사용하여 Microsoft 제품 지원에 문의하세요. Microsoft에서 Microsoft 제품의 결함으로 인해 문제가 확인된 경우 해당 인시던트에 대한 요금이 청구되지 않습니다.
이 문서에서는 애플리케이션의 안정성과 성능을 보장하는 데 필요한 도구와 정보를 제공합니다. 질문이 있는 경우 ASP.NET Web 에 게시하고 답변하기 위해 최선을 다할 것입니다. 행운을 빕니다!
저자 정보
Thomas Marquardt 는 Microsoft의 ASP.NET 팀의 개발자입니다. 그는 2000년 겨울부터 ASP.NET 애플리케이션의 성능 문제를 디버깅하고 조사해 왔습니다. 토마스는 Microsoft의 ASP.NET 개발 관리자인 드미트리 롭스만(Dmitry Robsman)에게 수년 동안 몇 시간 동안 도움과 지도를 해주신 것에 대해 감사를 표하고 싶습니다.