적용 대상: 인터넷 정보 서비스
PHP를 실행할 때 오류 페이지를 검사하여 오류 조건을 진단할 수 없는 경우가 있습니다. 이 오류는 다음과 같은 경우 발생할 수 있습니다.
- 어떤 URL에 오류가 발생하는지 알 수 없습니다.
- 오류는 간헐적으로 발생하며 수동으로 재현할 수 없습니다(오류는 자주 발생하지 않는 사용자 입력 또는 외부 운영 조건에 따라 달라질 수 있음).
- 이 오류는 프로덕션 환경에서만 발생합니다.
이러한 경우 오류가 무엇인지 정의하기가 어렵고 진단하기가 더 어렵습니다. 요청 로그 또는 오류 로그를 검사하여 오류를 일으키는 URL을 확인할 수 있지만 오류가 발생한 원인을 확인하는 데 여전히 문제가 있을 수 있습니다.
IIS(인터넷 정보 서비스)를 사용하면 실패한 요청 추적을 사용하여 이러한 어려운 오류 조건을 더 쉽게 추적하고 진단할 수 있으므로 특정 요청의 자세한 실행 추적을 자동으로 캡처하는 오류 정의를 만들 수 있습니다. IIS에서 추적을 사용하여 실패한 요청 문제 해결을 참조하고 실패한 요청 추적을 사용하여 다시 쓰기 규칙을 추적합니다.
PHP 진단을 돕기 위해 PHP에서 요청 입력 데이터 및 응답 데이터를 캡처하기 위해 이러한 추적을 수행할 수도 있습니다. 이렇게 하면 이러한 오류 조건을 진단하는 데 필요한 인사이트를 제공할 수 있습니다.
또 다른 상당히 일반적인 애플리케이션 문제는 코드가 멈추거나 리소스 집약적인 루프에 진입하는 것입니다. 이 오류는 다음과 같은 이유로 발생할 수 있습니다.
- 파일 또는 네트워크에서 차단 I/O 작업을 완료하는 데 시간이 오래 걸립니다(예: 원격 웹 서비스 또는 데이터베이스에 액세스할 때).
- 코드에는 CPU를 회전하거나 메모리를 할당하는 무한(또는 장기 실행) 루프에 들어가게 하는 버그가 있습니다.
- 공유 리소스 또는 잠금에서 코드가 중단되거나 교착 상태가 발생합니다.
이러한 조건으로 인해 사용자가 요청을 하는 데 긴 대기 시간 또는 시간 제한이 발생하며, 이 조건은 애플리케이션 및 서버 전체의 성능에도 부정적인 영향을 미칠 수 있습니다.
IIS는 현재 실행 중인 요청을 검사하여 어떤 요청이 매달려 있는지 확인하는 빠른 방법을 제공합니다.
실패한 요청 추적을 사용하여 알 수 없거나 재현하기 어려운 오류 진단
실패한 요청 추적은 IIS 모듈의 요청, 응답 및 풍부한 추적 이벤트에 대한 세부 정보를 검사하여 간헐적이거나 재현하기 어려운 오류 조건을 추적하고 오류 조건을 진단하는 효과적인 방법이 될 수 있습니다.
실패한 요청 추적은 특정 오류 정의를 충족하는 요청만 추적하도록 구성할 수 있으며 성공적인 요청에 대한 대부분의 추적 오버헤드를 방지할 수 있으므로 프로덕션 환경에서 사용할 수 있습니다.
사이트에 대해 실패한 요청 추적을 사용하도록 설정하려면(이 샘플에서는 TroubleshootingPhp를 사용) 다음 단계를 사용합니다.
IIS 관리자로 전환합니다. 닫힌 경우, 시작을 선택한 다음, 인터넷 정보 서비스(IIS) 관리자를 선택합니다.
서버 노드를 확장한 후, 사이트 노드를 확장합니다.
왼쪽의 트리 보기에서 사이트 이름을 찾아 선택합니다.
IIS에서 실패한 요청 추적 규칙을 두 번 클릭합니다.
[작업] 패널에서 [사이트 추적 편집]을 선택합니다.
사용 가능 확인란을 선택합니다.
확인을 선택합니다.
이제 실패한 요청 추적 규칙을 만듭니다. [작업] 패널에서 [추가]를 선택합니다.
모든 콘텐츠 옵션을 선택한 상태로 둡니다.
다음을 선택합니다.
상태 코드에 400-999를 입력합니다.
다음을 선택합니다.
기본 추적 공급자를 사용하도록 설정한 상태로 두고 마침을 선택합니다.
이제 요청을 수행할 수 있습니다. 사이트의 다른 사용자가 요청을 하고, 귀하는 그들의 요청이나 응답을 알지 못한다고 가정하십시오. 예를 들어 Internet Explorer를 사용하여 다음 요청을 수행합니다.
- 요청
http://localhost:84/hello.php
- 요청
http://localhost:84/products.php?productid=3
입니다. - 요청
http://localhost:84/products.php?productid=5
(이 페이지에서 오류가 발생)
- 요청
실패한 요청의 추적 로그를 찾습니다.
시작을 선택하고, 명령 프롬프트를 선택하여 명령 프롬프트 창을 엽니다.
다음 명령을 실행하여 사이트에 대해 생성된 추적 로그를 나열합니다.
%windir%\system32\inetsrv\appcmd.exe list traces /site.name:"TroubleshootingPhp"
다음과 유사한 출력이 표시됩니다.
TRACE "troubleshootingPhp/fr000001.xml" (url:http://localhost:84/products.php?product=5,statuscode:500,wp:2864)
출력은 요청에
/products.php?product=5
대한 추적 로그가 생성되어 HTTP 500 오류가 발생했음을 나타냅니다. 다음을 알려줍니다.- Products.php 페이지에서 오류가 발생했습니다.
- 오류를 발생시킨 입력은
product=5
다른 쿼리 문자열에 대한 오류가 표시되지 않기 때문에 가능성이 높습니다(이 페이지에 자주 액세스하는 경우 이 결론이 더 정확합니다. 이 경우 이 특정 쿼리 문자열에 대해서만 여러 오류가 표시됨).
이제 특정 추적 로그를 가져와 요청 및 오류의 가능한 원인에 대한 자세한 정보를 수집할 수 있습니다. 이렇게 하려면 명령 프롬프트에서 다음 명령을 실행합니다(이전 출력의 추적 로그에 따옴표 붙은 ID 사용).
%windir%\system32\inetsrv\appcmd.exe list traces /site.name:"TroubleshootingPhp" /text:*
다음과 유사한 출력이 있어야 합니다.
TRACELOG TRACE.NAME:" troubleshootingPhp/fr000001.xml" PATH:"C:\inetpub\logs\FailedReqLogFiles\W3SVC2\fr000001.xml" URL:"http://localhost:84/products.php?product=5" STATUSCODE:"500" SITE.ID:"2" SITE.NAME:"TroubleshootingPhp" WP.NAME:"2864" APPPOOL.NAME:"TroubleshootingPhp" verb:"GET" remoteUserName:"" userName:"" tokenUserName:"NT AUTHORITY\IUSR" authenticationType:"anonymous" activityId:"{ 00000000-0000-0000-1400-0080000000FA }" failureReason:"STATUS_CODE" triggerStatusCode:"500" timeTaken:"100" xmlns:freb:"http://schemas.microsoft.com/win/2006/06/iis/freb"
추적 로그를 검사합니다. 이전 출력에 지정된 경로를 사용하여 브라우저에서 추적 로그 파일을 엽니다(이 샘플 에서는 C:\inetpub\logs\FailedReqLogFiles\W3SVC2\fr000001.xml). 요약 탭은 요청에 대한 기본 정보를 제공합니다. 오류 상태가 PhP에서 발생했음을 나타내는 FastCGIModule에 의해 설정된 것을 확인할 수 있습니다. 다른 경우에는 다른 IIS 모듈에서 오류가 발생했음을 알 수 있습니다. 이 경우 로그의 풍부한 추적 정보를 사용하여 원인을 확인할 수 있습니다. 그러나 이 경우 오류에 대한 더 많은 인사이트를 얻으려면 PHP에서 생성된 응답을 실제로 확인해야 합니다.
압축 보기 탭을 선택합니다. 이 탭은 요청을 처리하는 동안 IIS 및 IIS 모듈에서 생성된 추적 이벤트의 자세한 목록을 보여 줍니다.
참고:
- GENERAL_REQUEST_START 이벤트에는 요청 URL, 동사, 사이트에 대한 런타임 정보 및 요청이 디스패치된 애플리케이션을 비롯한 몇 가지 기본 정보가 표시됩니다.
- GENERAL_REQUEST_HEADERS 이벤트는 헤더의 전체 목록을 제공하며, 경우에 따라 오류가 발생할 수 있는 사용자 입력을 결정할 때 중요할 수 있습니다.
- GENERAL_RESPONSE_HEADERS 및 GENERAL_RESPONSE_ENTITY_BUFFER 이벤트는 전체 응답 헤더와 클라이언트로 전송된 응답 본문을 제공합니다. 이 경우 응답 본문은 잘못된 제품 ID를 나타내는 오류를 진단하는 데 필요한 추가 정보를 제공합니다.
추적 로그를 검사하는 동안 고려해야 할 다른 섹션은 다음과 같습니다.
- 요청 요약 패널은 요청, 해당 결과에 대한 요약을 제공하고 요청 실행 중에 경고 또는 오류 이벤트를 강조 표시합니다.
- 요청 세부 정보 패널은 요청 실행에 대한 계층적 보기를 제공하므로 모듈 알림, 인증/권한 부여 등과 같은 다양한 범주별로 이벤트를 필터링할 수 있습니다. 또한 가장 오래 걸린 실행 부분을 이해하는 데 도움이 되는 성능 보기를 제공합니다.
- Compact View는 요청 실행에 대한 다양한 정보를 포함하여 이벤트의 전체 목록을 제공합니다. 대부분의 IIS 모듈은 요청 처리 및 결과의 다양한 측면을 이해하는 데 사용할 수 있는 실행에 대한 정보를 생성합니다. URL 재작성 또는 인증과 같은 복잡한 상호 작용 문제를 해결할 때 이 정보는 매우 중요할 수 있습니다.
현재 실행 중인 요청을 검사하여 중단된 요청 찾아내기
이렇게 하면 IIS에서 현재 실행 중인 요청을 검사하여 어떤 요청이 중단되는지 빠르게 확인할 수 있습니다.
프로그래밍 버그로 인해 무한 루프로 진입하는 페이지를 요청한다고 가정해 봅시다. 다음 단계에서는 이 페이지가 loop.php. 작업 관리자에서 Php-cgi.exe 사용 중이며 CPU의 약 100%를 소비하는 것을 확인할 수 있습니다(여러 CPU 코어가 있는 경우 프로세스에서 총 CPU 코어의 1/#을 소비하는 것을 볼 수 있음). 어떤 요청이 걸려 있는지 확인할 수 있습니다.
시작을 선택한 다음, 인터넷 정보 서비스(IIS) 관리자를 선택합니다.
왼쪽의 트리 뷰에서 서버 노드를 선택합니다.
IIS에서 작업자 프로세스를 두 번 클릭합니다.
애플리케이션 풀 이름 아래에서 애플리케이션 풀 이름을 두 번 클릭하여 요청 보기를 엽니다. (이 예제에서는 TroubleshootingPhp.)
웹 브라우저로 전환하고 페이지 시간이 초과된 경우 페이지를 새로 고칩니다. 이 작업은 이러한 단계 전체에서 수행해야 할 수 있습니다. IIS 관리자로 다시 전환한 다음 요청 보기를 새로 고칩니다.
이 샘플 의 /loop.php 문제 페이지에 대한 요청을 보여 주는 현재 실행 중인 요청 목록을 확인합니다. 요청 항목은 다음을 표시합니다.
- 요청이 일정 시간 동안 실행되고 있음을 나타냅니다(경과된 시간).
- 요청의 URL입니다(이 샘플에서는 /loop.php).
- 모듈 이름(FastCGIModule)입니다.
- 실행 단계(ExecuteRequestHandler)입니다.
보기를 여러 번 새로 고쳐 동일한 요청이 동일한 단계에서 계속 실행되는 것을 관찰하여 중단된 요청을 지적할 수 있습니다.
명령 프롬프트를 사용하여 어떤 요청이 중단되는지 확인합니다. 명령 프롬프트를 사용하여 관심 있는 요청(예: 특정 애플리케이션 또는 특정 URL에 대한 요청)을 필터링할 수 있습니다. 현재 실행 중인 요청을 모니터링하는 스크립트를 자동화하는 데 사용할 수 있습니다. 시작을 선택한 다음 명령 프롬프트를 선택하여 명령 프롬프트 창을 엽니다.
웹 브라우저로 전환한 다음 페이지를 새로 고칩니다
http://localhost:84/loop.php
. (loop.php는 샘플 이름입니다; 본인의 페이지 이름을 사용해야 합니다.) 다음 단계를 진행하기 위해 이 페이지를 지속적으로 새로 고쳐야 할 수 있습니다. 명령 프롬프트로 전환합니다.다음 명령을 실행하여 1초 이상 실행된 요청을 나열합니다.
%windir%\system32\inetsrv\appcmd.exe list requests /elapsed:1000
loop.php 대신 페이지 이름을 사용하여 다음과 유사한 출력을 가져옵니다.
REQUEST " fa000000080000026" (url:GET /loop.php, time:2840 msec, client:localhost, stage:ExecuteRequestHandler, module:FastCgiModule)
사용 가능한 요청 특성에 따라 조건 수를 지정하여 반환된 요청을 필터링합니다. 예를 들어 특정 URL에 대한 요청만 표시하려면 다음을 수행합니다.
%windir%\system32\inetsrv\appcmd.exe list requests /url:/loop.php /elapsed:1000
AppCmd 명령 연결을 사용하여 더 복잡한 쿼리를 수행할 수도 있습니다. 예를 들어 장기 실행 요청이 있는 모든 애플리케이션을 확인할 수 있습니다.
%windir%\system32\inetsrv\appcmd.exe list requests /elapsed:1000 /xml | %windir%\system32\inetsrv\appcmd list apps /in
다음과 유사한 애플리케이션 목록을 가져옵니다.
APP "troubleshootingPhp/" (applicationPool:troubleshootingPhp)
다음은 현재 요청 데이터를 기반으로 작업을 수행하는 예제입니다. 5초 이상 실행된 요청으로 애플리케이션 풀을 재활용합니다.
%windir%\system32\inetsrv\appcmd.exe list requests /elapsed:1000 /xml | %windir%\system32\inetsrv\appcmd list apppools /in /xml | %windir%\system32\inetsrv\appcmd recycle apppools /in
애플리케이션의 이름을 사용하여 다음 출력을 가져옵니다.
"TroubleshootingPhp" successfully recycled