Microsoft MVP성태의 닷넷 이야기
제니퍼 .NET: 12. COM+ 호출 모니터링 및 누수 확인 [링크 복사], [링크+제목 복사],
조회: 21260
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 3개 있습니다.)
COM+ 호출 모니터링 및 누수 확인


제니퍼를 이용하면 COM+ 개체를 사용하는 aspx(asmx,svc WCF...) 단의 호출을 모니터링하는 것이 가능합니다. 어떻게 되는지 한번 눈으로 확인을 해볼까요?

우선, 다음과 같이 각각 "라이브리러 활성화"로 등록된 COM+ 개체와 "서버 활성화"로 등록된 COM+ 개체를 호출한 코드를 예로 들어보겠습니다.

public partial class ComPlusServerTest : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // 라이브러리 활성화 COM+ 개체 호출
        using (MyComponentLibrary app = new MyComponentLibrary())
        {
            app.GetApp("test");
        }

        // 서버 활성화 - dllhost.exe에서 실행되는 COM+ 개체를 호출
        using (MyComponentServer app2 = new MyComponentServer())
        {
            app2.GetApp("test");
        }
    }
}

위의 코드가 실행되면 다음의 "[표 1]"과 같은 모니터링 결과를 확인할 수 있습니다.

[표 1: COM+ 호출 모니터링 트레이스 결과 화면]
UUID: 7aa8ee96ef535b90(8838576600742321040)     서버 시간: 22:33:20 198(1276522400198)
에이전트: V12     애플리케이션: /ComPlusServerTest.aspx(1065885031)
클라이언트 아이디: 254d96e273d812dc(2687970451960369884)     클라이언트 IP: 192.168.0.202     사용자 아이디: 
호출 시간: 22:33:20 195     종료 시간: 22:33:20 211     응답 시간: 16
CPU 시간: 0     SQL 시간: 16     Fetch 시간: 0     TX 시간: 0

[0000][22:33:20 195][    0][    0] START
[0000][22:33:20 195][    0][    0] [native:1]
[0003][22:33:20 195][    0][    0] COMPLUS-CALL[EntLibLibraryApp.MyComponentLibrary..ctor]

... [GetApp 메서드 호출 동안 발생한 모니터링 출력... 생략(예를 들어 SQL 호출 트레이스)] ...

[0016][22:33:20 211][    0][    0] COMPLUS-CALL[EntLibLibraryApp.MyComponentLibrary.GetApp] [16 ms]
[0017][22:33:20 211][    0][    0] COMPLUS-CALL[EntLibLibraryApp.MyComponentLibrary._internalDeactivate]
[0018][22:33:20 211][    0][    0] COMPLUS-CALL[EntLibLibraryApp.MyComponentLibrary.Dispose]
[0035][22:33:20 211][    0][    0] TX-CALL[COM+.EntLibServerApp.MyComponentServer..ctor] [16 ms]
[0036][22:33:20 211][    0][    0] TX-CALL[COM+.EntLibServerApp.MyComponentServer.GetApp] [25 ms]
[0037][22:33:20 211][    0][    0] TX-CALL[COM+.EntLibServerApp.MyComponentServer.Dispose] [16 ms]
[0038][22:33:20 211][    0][    0] END

DLL 유형의 로컬 호출이 되는 것은 "COMPLUS-CALL"로 표현되었고, 원격 호출이 되는 것은 "TX-CALL[COM+...]"로 표현이 되어 확연히 구분이 됩니다.

보시는 것처럼, 라이브러리 및 서버 활성화를 하는 COM+ 메서드 개체는 생성 및 해제까지 모두 메서드 호출로 이어지는 것을 확인할 수 있습니다.

COMPLUS-CALL[EntLibLibraryApp.MyComponentLibrary..ctor]
COMPLUS-CALL[EntLibLibraryApp.MyComponentLibrary.GetApp] [16 ms]
COMPLUS-CALL[EntLibLibraryApp.MyComponentLibrary._internalDeactivate]
COMPLUS-CALL[EntLibLibraryApp.MyComponentLibrary.Dispose]

왜 Dispose가 필요할까요? COM+ 개체는 닷넷으로 만들어져 있다고 해도 기반 인프라가 native 시절의 COM이기 때문에 반드시 COM Interop을 거치게 되어 있습니다. 따라서 Dispose를 명시적으로 해주지 않으면 native 자원이 새게 됩니다. (물론, 이후에 GC에 의해서 Dispose가 호출되긴 합니다.)

하지만, Dispose를 하지 않았을 때의 문제는 서버 활성화 COM+ 개체를 호출했을 때 더욱 심각해집니다.

TX-CALL[COM+.EntLibServerApp.MyComponentServer..ctor] [16 ms]
TX-CALL[COM+.EntLibServerApp.MyComponentServer.GetApp] [25 ms]
TX-CALL[COM+.EntLibServerApp.MyComponentServer.Dispose] [16 ms]

위와 같이, dllhost.exe라는 별도의 프로세스에서 활성화되는 서버 유형의 COM+ 개체 호출도 명백히 Dispose를 호출해 주어야만 dllhost.exe에서 호스팅되는 COM+ 자원이 정상적으로 해지될 수가 있습니다. 아마, COM+로 미들웨어를 구성하는 웹 사이트에서 겪는 대부분의 성능 문제가 위와 같이 COM+ 사용에 있어 Dispose를 호출하지 않는 것이라고 볼 수 있을 텐데요. 재미있는 점은, 대부분의 개발자들이 COM+ 개체 호출을 "메서드 호출" 정도로 가볍게 여기기 때문에 Dispose에 대해 소홀하다는 것입니다. 반면 WCF 등의 기술들처럼 명백히 원격 호출이라고 여겨지는 것들은 상대적으로 더 세심하게 Close를 해주는 것과 비교하면, 호출을 쉽게 해주는 COM+의 배려가 오히려 독이 되었다고 볼 수 있습니다.

그렇다면, 그러한 문제를 제니퍼로 잡아낼 수는 없을까요?

만약, 개발자가 아래와 같이 dispose를 명시적으로 호출하지 않는 aspx 웹 페이지를 만들어서 실행했다면,

public partial class ComPlusServerTest : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        MyComponentLibrary app = new MyComponentLibrary();
        app.GetApp("test");
    }
}

제니퍼의 X-View에는 아래와 같이 "빨간색" 점이 찍히게 되고,

jennifer_complus_res_leak_1.png

어떤 호출이었는지 확인하기 위해 마우스로 빨간색 점을 포함하는 영역을 드래그하면 아래와 같이 상세 화면이 나오게 됩니다.

jennifer_complus_res_leak_2.png

와~~~ 해당 호출에 대해서 "WARNING_RESOURCE_LEAK"이라고 경고가 나오고 그에 따른 웹 페이지의 경로를 "/ComplusServerTest.aspx"라고 일러주고 있습니다. 이제 개발자는 상세 화면의 프로파일링 결과에서 "Dispose"가 없는 부분을 확인하고 곧바로 해당 영역의 코드를 찾아서 Dispose 코드를 추가해 주면 됩니다.

jennifer_complus_res_leak_3.png

어떠세요? 이 정도면 COM+ 리소스 누수 문제로 고생하는 일이 확실히 줄어들 수 있겠죠! 아울러, 웹 사이트의 보다 나은 성능을 보장하면서!


[연관 글]






[최초 등록일: ]
[최종 수정일: 6/10/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 151  152  153  [154]  155  156  157  158  159  160  161  162  163  164  165  ...
NoWriterDateCnt.TitleFile(s)
1203정성태12/21/201125581제니퍼 .NET: 18. MEF가 적용된 ASP.NET 웹 사이트를 제니퍼 닷넷으로 모니터링 해본 결과! [6]
1202정성태12/21/201126069오류 유형: 144. The database '...' cannot be opened because it is version 661.
1201정성태12/14/201141122디버깅 기술: 47. .NET Reflector를 이용한 "소스 코드가 없는" 어셈블리 디버깅 [4]
1200정성태12/11/201126961디버깅 기술: 46. Windbg 확장 DLL 만들기 (2) - Debugger Extension API 사용파일 다운로드1
1199정성태12/11/201128374VC++: 55. JNI DLL 컴파일 시 x86과 x64의 Export된 함수의 이름이 왜 다를까요? [2]파일 다운로드1
1198정성태12/9/201132186디버깅 기술: 45. Windbg 확장 DLL 만들기 (1) - 스레드를 강제 종료시키는 명령어 [2]파일 다운로드1
1197정성태12/9/201129962.NET Framework: 282. Shader 강좌와 함께 배워보는 XNA Framework (2) - RenderMonkey의 Shader/Model 파일 연동파일 다운로드2
1196정성태12/9/201133145.NET Framework: 281. Shader 강좌와 함께 배워보는 XNA Framework (1) - 기초 프로그램 구조 [3]파일 다운로드2
1195정성태12/8/201147798오류 유형: 143. DXSDK_Jun10.exe 설치 시 "Error Code: S1023" 오류 해결하는 방법 [4]
1194정성태12/8/201135574개발 환경 구성: 137. Visual C++ 런타임 구성요소에 대한 디버그 버전 설치하는 방법
1193정성태12/8/201122612오류 유형: 142. Windows Phone SDK 7.1 설치 시 Expression Blend 제거를 요구하는 경우
1192정성태12/8/201125636개발 환경 구성: 136. Windows 7 SP1의 IIS에서 사용자 프로파일을 로드하는 방법
1191정성태12/6/201126813.NET Framework: 280. MVC3에서 JavaScriptSerializer 재정의하는 방법파일 다운로드1
1190정성태12/6/201129956오류 유형: 141. Visual C++ 컴파일 오류 - error C2275: 'xxxxx' : illegal use of this type as an expression [1]
1189정성태12/6/201137053VS.NET IDE: 70. Visual Studio에서 프로젝트 로드가 안된다면?
1188정성태12/3/201126152개발 환경 구성: 135. 마이크로소프트 TFS 호스팅 서비스 - Preview [3]
1187정성태12/2/201130810개발 환경 구성: 134. Robocopy 오류 및 종료 코드
1186정성태12/1/201132665.NET Framework: 279. WPF - 그리기 성능 및 Blurring 문제파일 다운로드1
1185정성태11/29/201123400.NET Framework: 278. WPF - Content의 Changed 이벤트에 해당하는게 뭔가요?파일 다운로드1
1184정성태11/29/201126201.NET Framework: 277. F#과 WPF가 어울리지 못하는 근본적인 이유 [2]
1183정성태11/26/201121700오류 유형: 140. Visual Studio 2010 - Floating된 에디트 윈도우가 사라지지 않는 경우 [2]
1182정성태11/25/201157430.NET Framework: 276. 중복 없는 숫자를 랜덤으로 배열하는 방법 [5]파일 다운로드1
1181정성태11/24/201127915디버깅 기술: 44. windbg의 mscordacwks DLL 로드 문제
1180정성태11/23/201137699.NET Framework: 275. 레지스트리 등록 및 Interop DLL 없이 COM 개체 사용하는 방법 [2]파일 다운로드1
1179정성태11/22/201128288.NET Framework: 274. ReaderWriterLockSlim은 언제 쓰는 걸까요? [4]파일 다운로드1
1178정성태11/19/201124787.NET Framework: 273. 설치된 .NET 버전에 민감한 코드를 포함하는 경우, 다중으로 어셈블리를 만들어야 할까요?파일 다운로드1
... 151  152  153  [154]  155  156  157  158  159  160  161  162  163  164  165  ...