Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

눈으로 확인하는 connectionManagement의 maxconnection 설정값


"눈으로 확인하는..." 시리즈 물이 될 것 같군요. ^^

눈으로 확인하는 maxWorkerThreads, minFreeThreads 설정값
; https://www.sysnet.pe.kr/2/0/983

이번에는 connectionManagement 노드에서 제공되는 maxconnection 값에 대한 테스트를 해보겠습니다. 이 값은 .NET 응용 프로그램에서 특정 호스트로 보내는 "동시 연결 수"를 제어합니다. 쉽게 풀어보면, 여러분들의 .NET 응용 프로그램에서 HttpWebRequest를 이용하여 다음과 같이 연결을 한다고 가정할 때,

string url = "http://testhost/test.aspx";
HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
                
using (HttpWebResponse httpResponse = req.GetResponse() as HttpWebResponse)
using (Stream stream = httpResponse.GetResponseStream())
using (StreamReader sr = new StreamReader(stream, Encoding.Default))
{
    string txt = sr.ReadToEnd();
}

만약, test.aspx 내의 코드 수행 시간이 10초가 걸리는 상황에서 위의 코드를 스레드 100개로 돌리면 maxconnection에 지정된 수의 스레드만 testhost 컴퓨터에 연결이 되고 나머지 스레드들의 HttpWebRequest 개체들은 10초가 지난 후 기존 연결들이 해제되고 나서야 하나씩 차례대로 접속할 수 있는 효과가 있습니다.

덧붙여, 아래의 문서에 보면 maxconnection에 대한 설명이 잘 나와 있습니다.

<add> Element for connectionManagement (Network Settings)
; https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/network/add-element-for-connectionmanagement-network-settings

Don't forget to tune your application 
; http://weblogs.asp.net/johnbilliris/archive/2010/06/30/don-t-forget-to-tune-your-application.aspx

대부분의 app/web.config 파일에는 connectionManagement 설정이 없는데요. 그렇다면 기본값은 몇일까요?




확인을 위해 간단한 테스트 환경을 구성했습니다.

A, B 호스트를 마련했고, A 호스트의 test.aspx는 B 호스트의 delay.aspx를 호출하도록 했습니다. delay.aspx는 일부러 Page_Load에서 Thread.Sleep(60 * 1000)을 해서 60초의 지연 시간을 갖고!

(별다른 의미는 없지만, B 호스트는 Web Garden == 2로 설정했습니다.)

부하 발생기를 이용해서 A 호스트의 test.aspx에 요청을 집중했더니 아래와 같이 maxconnection == 10의 결과가 나왔습니다.

maxconnection_settings_affect_1.png

위의 그림에서 "W11"이 "A 호스트"이고, "W21", "W22"는 "Web Garden"이 2개로 설정된 "B 호스트"의 웹 응용 프로그램을 나타냅니다.

보시는 것처럼, test.aspx에서 HttpWebRequest를 이용하여 "http://bhost/delay.aspx"로 호출했을 때 최대 10개의 연결만 맺어지는 것을 볼 수 있습니다. 즉, connectionManagement의 maxconnection 기본값은 10이 됩니다.

확실히 하기 위해 이 값을 30으로 바꿔보았습니다.

<system.net>
    <connectionManagement>
        <add address="*" maxconnection="30" />
    </connectionManagement>
</system.net>

자, 그럼 결과가 어떻게 나올까요? ^^ 예상하시는 것처럼 "B 호스트"로의 연결은 각각 15개씩 총 30개의 연결로 제한이 됩니다.

maxconnection_settings_affect_2.png




한 가지 짚고 넘어가야 할 것이 있는데요. 문서가 약간 혼동스럽다는 점입니다. maxconnection이 지정되어 있지 않으면 기본값이 2라고 되어 있는데요.

maxconnection - The maximum number of connections allowed to a server. If not supplied, the default is 2.


"%Program Files%\Microsoft Visual Studio 10.0\xml\Schemas\DotNetConfig35.xsd" 파일에 명시된 바에 의하면 maxconnection은 생략할 수 없는 "required" 속성을 가지고 있습니다.

<xs:element name="connectionManagement" vs:help="configuration/system.net/connectionManagement">
    <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
            <xs:element name="add" vs:help="configuration/system.net/connectionManagement/add">
                <xs:complexType>
                    <xs:attribute name="address" type="xs:string" use="required" />
                    <xs:attribute name="maxconnection" type="xs:int" use="required" />
                    <xs:attribute name="lockAttributes" type="xs:string" use="optional" />
            ...[생략]...

그런데, 실제로 ^^; 생략이 되어 다음과 같이 설정하는 것이 가능합니다.

<system.net>
    <connectionManagement>
        <add address="*" />
    </connectionManagement>
</system.net> 

다시 부하 발생기로 테스트해 보면 값이 어떻게 나올까요?

예상했던 2가 아니라... 1입니다. (혹시, 제가 테스트를 잘못한 것 같다면 덧글 부탁드립니다.)

maxconnection_settings_affect_3.png




고객사에서 오류 문의가 왔습니다. 제니퍼 닷넷에서 다음과 같은 오류가 보고된 것입니다.

...[생략]...
[0005][13:39:23 477][ 15][ 15] TX-CALL[WebReq.http://[...this_public_domain_name...]/top.aspx] [15 ms]
[0006][13:39:23 477][ 0][ 0] SOCKET-CLOSE R=52174,W=106,uid=7568243 
[0007][13:40:03 523][40,046][ 16] TX-CALL[WebReq.http://[...this_public_domain_name...]/bottom.aspx] [40,046 ms]
[0008][13:40:03 523][ 0][ 0] TX-EXCEPTION [System.Net.WebException: 작업 시간이 초과되었습니다. ...[이하 콜스택 생략]... 

그런데... 가만 보면 해당 웹 페이지의 구성 자체가 재미있습니다. 보통 웹 페이지를 만들면 내부에 레이아웃을 구성하게 되는데요. 위의 고객 사이트는 웹 페이지의 top과 bottom에 해당하는 내용을 별도의 aspx로 빼고 사용자로부터 요청이 왔을 때 HttpWebRequest 개체를 이용해서 직접 top/bottom 관련해서 aspx를 호출하여 내용을 가져온 후 화면에 추가하는 것이었습니다.

위와 같은 구성이 성능에 어떤 영향을 미칠까요?

1) 우선, 해당 고객 사이트가 web.config에 connectionManagement / maxconnection 설정을 하지 않았다고 가정해 보겠습니다. 이 글의 처음에 설명했던 것처럼 특정 호스트에 대해 동시 연결이 기본값 10으로 동작하기 때문에, 위의 웹 사이트는 마치 10개의 상한을 가진 세마포어를 사용하는 효과를 가지게 됩니다. 동시 연결 10개 이후부터는 쓰레드들이 대기 현상이 발생하게 되고 사용자가 폭주하는 시간에는 그 현상이 더욱 심하게 됩니다.

게다가 위에서는 top과 bottom에 대해 각각 요청을 보냈기 때문에 스레드 대기 현상은 더욱 심해집니다.

2) 두 번째 문제는, HttpWebRequest 요청의 URL에 내부 IP가 아닌, 일반 사용자들이 접근할 때와 동일한 공용 DNS 이름을 사용했다는 것입니다. 이렇게 되면 내부 IP가 아닌 외부 공용 IP가 구해지게 되고, 방화벽/NAT/L4 장비를 거쳐서 호출이 되어 응답 시간이 늘어나게 됩니다.

3) 세 번째 문제는, dead-lock 문제에 빠질 수 있습니다. 이에 대해서는 지난번에도 한번 사례를 설명했었습니다.

제니퍼 닷넷 적용 사례 (2) - 웹 애플리케이션 hang의 원인을 알려주다.
; https://www.sysnet.pe.kr/2/0/1117

위의 글에서는 config.xml 파일 하나를 서비스하는 유형이라서 간단하게 AppPool을 별도로 생성하여 스레드 풀을 새롭게 할당함으로써 해결을 했는데요. System.Net.WebException 예외가 발생한 이번 글의 고객사 경우에는 문제가 좀 복잡해 질 수 있습니다. 왜냐하면, top/bottom.aspx 요청을 받는 그 웹 사이트는 그 외에도 많은 요청을 받아서 처리할 수 있는 구조였기 때문입니다.

가정을 해볼까요? 사용자가 갑자기 몰려서 L4로 묶인 호스트 중에서 "192.168.0.10" 서버가 동시에 1,200개의 요청을 받았다고 해보겠습니다. 그 서버는 maxWorkerThreads == 100 상태에서 쿼드 코어라면 총 400개의 동시 요청만을 처리할 수가 있습니다. 나머지 800개는 IIS가 요청 대기 큐에 쌓아두고 앞서의 처리가 끝나면 차례대로 처리를 할 텐데요. 설상 가상으로 DB까지 지연되면서 하나의 aspx 처리 시간이 5초가 걸리는 상황이 발생한다고 하면?

그런 와중에 "192.168.0.11" 서버로 top/bottom.aspx를 포함한 웹 페이지 요청이 발생했고 하필 그것이 "192.168.0.10" 서버로 전달되었다고 하면 어떤 일이 벌어질까요? 현재 10번 서버에 발생한 요청만 처리하는데 1,200 / 400 = 3 * 5초 == 15초가 소요되어 11번 서버로 요청을 보냈던 사용자는 11번 서버가 한가로운데도 불구하고 15초를 대기한 후에야 정상적인 aspx 웹 페이지를 볼 수 있게 됩니다.

결론적으로, 아무리 어떤 이유를 갖다댄다 해도... 하나의 aspx에서 top/bottom.aspx의 내용을 별도의 HTTP 요청으로 분리해서 구하는 것은 꽤나 불합리한 구조입니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







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

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

비밀번호

댓글 작성자
 



2017-12-26 09시45분
[몬난아] 예전글이라 답변이 달릴지 모르겠군요..
https://docs.microsoft.com/en-us/aspnet/web-forms/overview/performance-and-caching/using-asynchronous-methods-in-aspnet-45 게시글을 보다가 여기까지 왔습니다.

하단에 maxconnection관련 해서 12 * 4(cpu) = 48 부분인데요.

이게 기본설정이면 2008r2이상에서는 4cpu에서 48개정도의 동시 처리가 불가능한것인가요? 좀 혼란스러운게.. IIS같은경우는 1개의 프로세스에 25개의 Thread설정이 기본값인데. 이것과상관관계가 어떻게 되는지 머리속에 그려지지 않내요..

이럴경우 서비스 4.0으로 서비스하고 있는 프로젝트들은 좀 수동으로 늘려주는게 유리한것인지 해서 질문드립니다. 4.5가 5000이 기본값이면, 48이 아닌 여유있게 1000~3000을 줘도 여유로울것 같은설정인데..

그리고 .NET 4.5이상에서는 5000개가 기본값인것도 갭이 상당하내요..

질문이 두서없군요.. 저는 여태까지는 IIS에 1개의 어플리케이션은 별도로 옵션을 수정하지 않는다면
1개프로세스안에서 > 25개의 Thread가 대기중인상태이고 3000개 까지 큐를 받을수 있으며 큐에 쌓인순서대로 25개의 Thread 25개가 순차적으로 처리해나간다였는데.
여기 개념사이에 CPU별로 12개씩 동시 처리 여부가 어디에? 들어가야하는걸로 계산해야하는지... 그게 좀 혼란스럽내요..
[guest]
2017-12-26 09시53분
[몬난아] 큐길이 설정이.. IIS에서도 ASP 하위에 큐길이의 기본값은 3천이고.. 응용프로그램풀의 기본값은 1000이군요.
이럴경우 ASP쪽의 설정은 Classic ASP에서이고.. 닷넷은 응용프로그램풀의 큐설정을 따르는것인가요... 이게 질문의 범위가 커져버렸습니다.

만약그런것이라면 ASP 하위에 프로세스 당 Thread제한역시 ASP전용이 되는것이고 .NET은 maxconnection 인것인지..
몇가지가 기존에 알던것과 틀리고 중복된.. 혼란스럽네요.. 시간이 나시면 간단히 답변부탁드립니다
수고하세요
[guest]
2017-12-26 02시03분
[몬난아] 아 다시 차근히 읽으니 해당설정은 응용에서 특정호스트로 보내는 작업에 제한이군요....
[guest]
2019-07-30 12시57분
C:\Windows\Microsoft.NET\Framework\v2.0.50727\Aspnet.config

<system.web>
  <applicationPool
       maxConcurrentRequestsPerCPU="12"
       maxConcurrentThreadsPerCPU="0"
       requestQueueLimit="5000"/>
</system.web>
정성태

... 61  62  63  64  65  66  67  68  69  [70]  71  72  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
12186정성태3/12/202017416오류 유형: 604. The SysVol Permissions for one or more GPOs on this domain controller and not in sync with the permissions for the GPOs on the Baseline domain controller.
12185정성태3/11/202018036오류 유형: 603. The browser service was unable to retrieve a list of servers from the browser master...
12184정성태3/11/202019959오류 유형: 602. Automatic certificate enrollment for local system failed (0x800706ba) The RPC server is unavailable. [3]
12183정성태3/11/202017774오류 유형: 601. Warning: DsGetDcName returned information for \\[...], when we were trying to reach [...].
12182정성태3/11/202019241.NET Framework: 901. C# Windows Forms - Vista/7 이후의 Progress Bar 업데이트가 느린 문제파일 다운로드1
12181정성태3/11/202019527기타: 76. 재현 가능한 최소한의 예제 프로젝트란? - 두 번째 예제파일 다운로드1
12180정성태3/10/202015983오류 유형: 600. "Docker Desktop for Windows" - EXPOSE 포트가 LISTENING 되지 않는 문제
12179정성태3/10/202027720개발 환경 구성: 481. docker - PostgreSQL 컨테이너 실행
12178정성태3/10/202019800개발 환경 구성: 480. Linux 운영체제의 docker를 위한 tcp 바인딩 추가 [1]
12177정성태3/9/202019019개발 환경 구성: 479. docker - MySQL 컨테이너 실행
12176정성태3/9/202018526개발 환경 구성: 478. 파일의 (sha256 등의) 해시 값(checksum) 확인하는 방법
12175정성태3/8/202018562개발 환경 구성: 477. "Docker Desktop for Windows"의 "Linux Container" 모드를 위한 tcp 바인딩 추가
12174정성태3/7/202017947개발 환경 구성: 476. DockerDesktopVM의 파일 시스템 접근 [3]
12173정성태3/7/202019270개발 환경 구성: 475. docker - SQL Server 2019 컨테이너 실행 [1]
12172정성태3/7/202023806개발 환경 구성: 474. docker - container에서 root 권한 명령어 실행(sudo)
12171정성태3/6/202018899VS.NET IDE: 143. Visual Studio - ASP.NET Core Web Application의 "Enable Docker Support" 옵션으로 달라지는 점 [1]
12170정성태3/6/202016926오류 유형: 599. "Docker Desktop is switching..." 메시지와 DockerDesktopVM CPU 소비 현상
12169정성태3/5/202019468개발 환경 구성: 473. Windows nanoserver에 대한 docker pull의 태그 사용 [1]
12168정성태3/5/202020686개발 환경 구성: 472. 윈도우 환경에서의 dockerd.exe("Docker Engine" 서비스)가 Linux의 것과 다른 점
12167정성태3/5/202019090개발 환경 구성: 471. C# - 닷넷 응용 프로그램에서 DB2 Express-C 데이터베이스 사용 (3) - ibmcom/db2express-c 컨테이너 사용
12166정성태3/4/202019518개발 환경 구성: 470. Windows Server 컨테이너 - DockerMsftProvider 모듈을 이용한 docker 설치
12165정성태3/2/202018494.NET Framework: 900. 실행 시에 메서드 가로채기 - CLR Injection: Runtime Method Replacer 개선 - 네 번째 이야기(Monitor.Enter 후킹)파일 다운로드1
12164정성태2/29/202019550오류 유형: 598. Surface Pro 6 - Windows Hello Face Software Device가 인식이 안 되는 문제
12163정성태2/27/202017873.NET Framework: 899. 익명 함수를 가리키는 delegate 필드에 대한 직렬화 문제
12162정성태2/26/202021745디버깅 기술: 166. C#에서 만든 COM 객체를 C/C++로 P/Invoke Interop 시 메모리 누수(Memory Leak) 발생 [6]파일 다운로드2
12161정성태2/26/202017743오류 유형: 597. manifest - The value "x64" of attribute "processorArchitecture" in element "assemblyIdentity" is invalid.
... 61  62  63  64  65  66  67  68  69  [70]  71  72  73  74  75  ...