2016-10-30 3 views
2

async/await가 IIS 스레드와 관련된 문제를 해결하지 못하는 이유는 무엇입니까?IIS에서 async await이 작동하지 않는 이유는 무엇입니까? 그러나 IIS Express에서 작동 중입니다.

IIS 스레드를 제한하고 IIS를 사용할 때 IIS 제한을 사용할 수 없다는 것을 알았습니다.

이 문제를 반복하기 위해 HomeController에서 2 가지 방법을 추가합니다. 그 중 하나 (메서드)는 Thread.Sleep을 사용하고 다른 하나는 async/await를 사용합니다.

물론이 문제를 자세히 설명하기 위해 로거 (NLog)를 사용합니다.

나는 하나의 URL에 대해 100 개의 병렬 요청으로 apache-jmeter-3.0을 스트레스 테스트로 사용합니다.

테스트 실행 시간이 IIS에서 거의 동일하고 IIS에서 동일하지 않은 경우 매우 놀랐습니다.

HomeController

에서 일부 코드
[SessionState(SessionStateBehavior.Disabled)] 
public class HomeController : Controller 
{ 
    private const int _waitTimeout = 30000; 
    private const string _beginFmt = "Begin method; Count = {0}; OperId = {1};"; 
    private const string _endFmt = "End method ; Count = {0}; OperId = {1};"; 

    private static volatile int _counter = 0; 
    private static Logger _logger = LogManager.GetCurrentClassLogger(); 

    public JsonResult GetWithThreadSleep() 
    { 
     Guid operId = Guid.NewGuid(); 

     _logger.Info(_beginFmt, Interlocked.Increment(ref _counter), operId); 

     Thread.Sleep(_waitTimeout); 

     _logger.Info(_endFmt, Interlocked.Decrement(ref _counter), operId); 

     return Json(null, JsonRequestBehavior.AllowGet); 
    } 

    public async Task<JsonResult> GetWithTaskAwait() 
    { 
     Guid operId = Guid.NewGuid(); 

     _logger.Info(_beginFmt, Interlocked.Increment(ref _counter), operId); 

     await Task.Delay(_waitTimeout); 

     _logger.Info(_endFmt, Interlocked.Decrement(ref _counter), operId); 

     return Json(null, JsonRequestBehavior.AllowGet); 
    } 
} 

로그 형식

<target xsi:type="File" 
      name="f" fileName="${basedir}/logs/${shortdate}.log" 
      layout="${threadid} @ ${date:format=HH\:mm\:ss} @ ${level} @${aspnet-sessionid} @ ${message} @ ${callsite:className=False}" 
    /> 

테스트 시나리오 하나 : 나는 방법 GetWithTaskAwait 100 병렬 GET 요청을 보내고 요청을 처리 할 수있을 것으로 기대 스레드가 다시 사용해야하므로 5 분보다 빠릅니다.

하지만이 경우는 아닙니다. 내가 방법 GetWithThreadSleep 100 병렬 GET 요청을 전송하고 스레드가 다시 사용하지 않아야하기 때문에 요청, 동일한 5 분 처리 할 수있을 것으로 기대 : 시험 시간 5 분

1 @ 23:43:54 @ Info @ @ MVC Count = 1; @ .ctor 
1 @ 23:43:54 @ Info @ @ APP Count = 1; @ Application_Start 
11 @ 23:44:06 @ Info @ @ MVC Count = 2; @ .ctor 
... 
13 @ 23:45:36 @ Info @ @ End method ; Count = 8; OperId = 28818fba-5535-4c01-9d6d-5efa3943cf37; @ MoveNext 
19 @ 23:45:36 @ Info @ @ Begin method; Count = 9; OperId = c3cd3339-ec29-4625-adb9-62d5c72831b0; @ GetWithTaskAwait 
12 @ 23:45:36 @ Info @ @ End method ; Count = 9; OperId = d1686c05-ca7a-400c-8c17-43dfb7b9218a; @ MoveNext 
16 @ 23:45:36 @ Info @ @ Begin method; Count = 10; OperId = c1ec5517-649c-4733-9db3-e666e648abae; @ GetWithTaskAwait 
13 @ 23:45:36 @ Info @ @ End method ; Count = 9; OperId = fbcfc9d9-fb84-456b-82a1-a0d593ef0815; @ MoveNext 
... 
26 @ 23:49:06 @ Info @ @ End method ; Count = 8; OperId = 766d4bc5-3739-4e20-a242-1f114dd44442; @ MoveNext 
22 @ 23:49:06 @ Info @ @ End method ; Count = 7; OperId = 0ba18b30-11c9-49fe-8c94-40bbfa817e88; @ MoveNext 
16 @ 23:49:06 @ Info @ @ End method ; Count = 9; OperId = 6d7afd57-6128-4bee-bf32-92de7cfc6a34; @ MoveNext 
26 @ 23:49:06 @ Info @ @ End method ; Count = 6; OperId = 4c022744-9932-4f94-be1d-b982e36460f2; @ MoveNext 
22 @ 23:49:06 @ Info @ @ End method ; Count = 5; OperId = 05476e6a-106f-4da5-b99b-098b90dbab89; @ MoveNext 
16 @ 23:49:07 @ Info @ @ End method ; Count = 4; OperId = 3aba1ad2-56b0-4cf5-8aee-7e918eca9fba; @ MoveNext 
27 @ 23:49:07 @ Info @ @ End method ; Count = 3; OperId = ef972cdd-7992-4816-9452-ecabaf189767; @ MoveNext 
15 @ 23:49:07 @ Info @ @ End method ; Count = 2; OperId = 9a0f735e-bf6b-4217-b2ef-8abd9ce01d27; @ MoveNext 
30 @ 23:49:07 @ Info @ @ End method ; Count = 0; OperId = cc75b44a-4e8d-4534-9906-40bddc027267; @ MoveNext 
33 @ 23:49:07 @ Info @ @ End method ; Count = 1; OperId = bbef36b3-051b-444d-858a-2766bcfcd12b; @ MoveNext 
... 
26 @ 23:49:49 @ Info @ @ MVC Count = 10; @ Dispose 
30 @ 23:50:19 @ Info @ @ MVC Count = 9; @ Dispose 
16 @ 23:50:49 @ Info @ @ MVC Count = 8; @ Dispose 

테스트 시나리오 두 같습니다.

1 @ 00:15:41 @ Info @ @ MVC Count = 1; @ .ctor 
1 @ 00:15:41 @ Info @ @ APP Count = 1; @ Application_Start 
11 @ 00:16:14 @ Info @ @ MVC Count = 2; @ .ctor 
... 
15 @ 00:16:15 @ Info @ @ Begin method; Count = 8; OperId = cedb5075-405c-4c23-93cb-388dc34537ba; @ GetWithThreadSleep 
17 @ 00:16:15 @ Info @ @ MVC Count = 10; @ .ctor 
17 @ 00:16:15 @ Info @ @ Begin method; Count = 9; OperId = 777d7464-f900-48c1-991f-ef8c8f7e6e86; @ GetWithThreadSleep 
18 @ 00:16:16 @ Info @ @ MVC Count = 11; @ .ctor 
18 @ 00:16:16 @ Info @ @ Begin method; Count = 10; OperId = f9b4b717-94a5-4196-958f-c1234d19514c; @ GetWithThreadSleep 
12 @ 00:16:45 @ Info @ @ End method ; Count = 8; OperId = 9e40acd4-888f-4656-a5a3-c5a1d210cc88; @ GetWithThreadSleep 
5 @ 00:16:45 @ Info @ @ End method ; Count = 9; OperId = b068e03e-37e9-446e-ad42-c9ab4c30da93; @ GetWithThreadSleep 
11 @ 00:16:45 @ Info @ @ End method ; Count = 7; OperId = 22e510e5-62f7-4bc8-8ab0-fdeb3080e250; @ GetWithThreadSleep 
... 
18 @ 00:21:15 @ Info @ @ End method ; Count = 2; OperId = 169ef436-6b27-4f4c-a3ca-0b18a5a796cf; @ GetWithThreadSleep 
13 @ 00:21:16 @ Info @cubgm2zsojblkhrwwpixaaej @ End method ; Count = 1; OperId = ee346be8-17c5-45ac-88b5-67e724250bbf; @ GetWithThreadSleep 
12 @ 00:21:16 @ Info @ @ End method ; Count = 0; OperId = 68d5deaa-95d6-4627-a129-144ffafcc2ef; @ GetWithThreadSleep 
13 @ 00:22:11 @ Info @ @ MVC Count = 10; @ Dispose 
9 @ 00:22:41 @ Info @ @ MVC Count = 9; @ Dispose 

중요 정보 :

  • IIS 버전 10.0.14393.0
  • .NET 프레임 워크 4.5.1
  • 윈도우 10 프로

당신은 GitHub

에서 전체 솔루션을 다운로드 할 수 있습니다
+0

내가 물어 봐도 될까요? 전에는 들어 보지 못했습니다. – Schadensbegrenzer

+0

@Schadensbegrenzer, 정적 변수의 값을보고 로그 파일을 분석합니다. 메서드가 시작되기 전에 메서드 시작 및 감소에서 정적 변수의 값을 증가시킵니다. – StuS

+0

@StanislavFlusov : 가장 먼저 확인해야 할 것은 요청에 대한 세션 상태입니다. 세션 상태를 해제 했습니까? –

답변

2

데스크톱 OS의 Windows (7/8/10)는 요청을 동시 10 개로 제한합니다.

서버 OS (2008/2012/2016)에서 해당 제한이 존재하지 않습니다.

IIS Express에는 해당 제한도 없습니다.

이 제한의 이유는 프로덕션 목적으로 데스크톱 OS에서 IIS를 사용하지 않기 때문입니다. 당신은 IIS에서 10 개 스레드의 한계를 표시하는 방법

https://weblogs.asp.net/owscott/windows-8-iis-8-concurrent-requests-limit

+1

데스크톱 및 서버 운영 체제 (Windows 10 및 Windows Server 2012 R2)에서 GitHub의 코드를 실행하십시오. Windows 10에서는 실제로 설명한 것처럼 10 개의 동시 요청으로 제한됩니다. W2K12에서 나는 수십개의 요청을 문제없이 동시에 실행할 수있었습니다. – IdoFlatow

1

IIS는 스레드가 아니라 동시 요청 (또는 연결, 확실하지 않음)을 제한합니다. 비동기 대기는 그 한계를 우회 할 수 없습니다.

+1

하지만이 실험에서는 async/await가 IIS Express에서 완벽하게 실행되지만 IIS에서는 실행되지 않는 것으로 나타났습니다. – StuS

+1

당신은 IIS 표현이 스로틀 (throttle)하지 않기 때문에 부분이 괜찮은 것처럼 보인다고 말했습니까? 그리고 나는 기다림이 당신이 IIS의 한계를 우회하는 것을 허용하지 않는다고 말합니다. 내가 놓친 게 있니? – usr