program story

더 큰 스레드 풀을 사용하는 대신 비동기 요청을 사용하는 이유는 무엇입니까?

inputbox 2020. 11. 15. 11:15
반응형

더 큰 스레드 풀을 사용하는 대신 비동기 요청을 사용하는 이유는 무엇입니까?


네덜란드의 Techdays에서 Steve Sanderson은 C # 5, ASP.NET MVC 4 및 비동기 웹에 대한 프레젠테이션을했습니다 .

그는 요청이 완료되는 데 오랜 시간이 걸리면 스레드 풀의 모든 스레드가 바쁘고 새로운 요청이 기다려야한다고 설명했습니다. 서버가 부하를 처리 할 수없고 모든 것이 느려집니다.

그런 다음 비동기 웹 요청을 사용하면 작업이 다른 스레드에 위임되고 스레드 풀이 새로운 수신 요청에 신속하게 응답 할 수 있기 때문에 어떻게 성능이 향상되는지 보여주었습니다. 그는 심지어 이것을 시연했고 50 개의 동시 요청이 처음에는 50 * 1 초가 걸렸지 만 비동기 동작은 총 1,2 초 밖에 걸리지 않는다는 것을 보여주었습니다.

그러나 이것을 본 후에도 여전히 몇 가지 질문이 있습니다.

  1. 더 큰 스레드 풀을 사용할 수없는 이유는 무엇입니까? async / await를 사용하여 다른 스레드를 더 느리게 가져온 다음 처음부터 스레드 풀을 늘리지 않습니까? 우리가 실행하는 서버가 갑자기 더 많은 스레드를 얻는 것과 같지 않습니까?

  2. 사용자의 요청은 여전히 ​​비동기 스레드가 완료되기를 기다리고 있습니다. 풀의 스레드가 다른 작업을 수행하는 경우 'UI'스레드가 어떻게 바쁘게 유지됩니까? 스티브는 '무언가 완료되면 아는 스마트 커널'에 대해 언급했습니다. 어떻게 작동합니까?


이것은 매우 좋은 질문이며 비동기 IO가 왜 그렇게 중요한지 이해하는 것이 중요합니다. 새로운 async / await 기능이 C # 5.0에 추가 된 이유는 비동기 코드 작성을 단순화하기 위해서입니다. 서버에서 비동기 처리에 대한 지원은 새로운 것은 아니지만 ASP.NET 2.0부터 존재합니다.

Steve가 보여준 것처럼 동기 처리를 통해 ASP.NET (및 WCF)의 각 요청은 스레드 풀에서 하나의 스레드를 가져옵니다. 그가 시연 한 문제는 " 스레드 풀 부족 " 이라는 잘 알려진 문제 입니다. 서버에서 동기식 IO를 만드는 경우 스레드 풀 스레드는 IO 기간 동안 차단 된 상태로 유지됩니다 (아무것도하지 않음). 스레드 풀의 스레드 수에 제한이 있기 때문에로드시 모든 스레드 풀 스레드가 IO를 기다리면서 차단되고 요청이 큐에 들어가기 시작하여 응답 시간이 늘어날 수 있습니다. 모든 스레드가 IO가 완료되기를 기다리고 있기 때문에 CPU 점유율이 0 %에 가깝습니다 (응답 시간이 지붕을 통과하더라도).

당신이 묻는 것은 ( 왜 더 큰 스레드 풀을 사용할 수 없습니까? ) 아주 좋은 질문입니다. 사실, 이것이 지금까지 대부분의 사람들이 스레드 풀 부족 문제를 해결 한 방법입니다. 스레드 풀에 더 많은 스레드가있을뿐입니다. Microsoft의 일부 문서는 스레드 풀 부족이 발생할 수있는 상황에 대한 수정 사항으로도 표시합니다. 이것은 수용 가능한 솔루션이며 C # 5.0까지는 코드를 완전히 비동기로 다시 작성하는 것보다 훨씬 쉬웠습니다.

하지만 접근 방식에는 몇 가지 문제가 있습니다.

  • 모든 상황에서 작동하는 값은 없습니다 . 필요한 스레드 풀 스레드 수는 IO 기간과 서버의로드에 따라 선형 적으로 달라집니다. 불행히도 IO 대기 시간은 대부분 예측할 수 없습니다. 예를 들면 다음과 같습니다. ASP.NET 응용 프로그램의 타사 웹 서비스에 HTTP 요청을하는 경우 완료하는 데 약 2 초가 걸립니다. 스레드 풀 부족이 발생하여 스레드 풀 크기를 200 개 스레드로 늘리기로 결정한 다음 다시 정상적으로 작동하기 시작합니다. 문제는 아마도 다음 주에 웹 서비스에 기술적 문제가 발생하여 응답 시간이 10 초로 늘어날 것이라는 것입니다. 스레드가 5 배 더 오래 차단되기 때문에 갑작스런 스레드 풀 고갈이 다시 발생하므로 이제 스레드 수를 1,000 개로 5 배 늘려야합니다.

  • 확장 성 및 성능: 두 번째 문제는 그렇게하면 요청 당 하나의 스레드를 계속 사용한다는 것입니다. 스레드는 값 비싼 리소스입니다. .NET의 각 관리 스레드에는 스택에 대해 1MB의 메모리 할당이 필요합니다. 5 초 동안 지속되는 IO를 만들고 초당 500 개의 요청을로드하는 웹 페이지의 경우 스레드 풀에 2,500 개의 스레드가 필요합니다. 즉, 아무것도하지 않는 스레드 스택에 대해 2.5GB의 메모리가 필요합니다. 그런 다음 컨텍스트 전환 문제가 있습니다.이 문제는 컴퓨터의 성능에 큰 영향을 미칩니다 (웹 애플리케이션뿐만 아니라 컴퓨터의 모든 서비스에 영향을 미침). Windows는 대기중인 스레드를 무시하는 데 상당히 효과적이지만 그렇게 많은 수의 스레드를 처리하도록 설계되지 않았습니다.

따라서 스레드 풀의 크기를 늘리는 것이 해결책이며, 사람들은 10 년 동안 (마이크로 소프트 자체 제품에서도) 그렇게 해왔지만 메모리 및 CPU 사용량 측면에서 확장 성과 효율성이 떨어지며 항상 기아를 유발할 수있는 IO 대기 시간의 갑작스러운 증가의 자비. C # 5.0까지 비동기 코드의 복잡성은 많은 사람들에게 문제가 될 가치가 없었습니다. async / await는 지금과 같이 모든 것을 변경하므로 비동기 IO의 확장 성의 이점을 누리면서 동시에 간단한 코드를 작성할 수 있습니다.

자세한 내용 : http://msdn.microsoft.com/en-us/library/ff647787.aspx " 웹 서비스 호출이 진행되는 동안 추가 병렬 처리를 수행 할 기회가있을 때 비동기 호출을 사용하여 웹 서비스 또는 원격 개체를 호출합니다. 나가는 웹 서비스 호출은 ASP.NET 스레드 풀의 스레드를 사용하여 이루어지기 때문에 가능하면 웹 서비스에 대한 동기 (차단) 호출을 피하십시오. 호출을 차단하면 다른 들어오는 요청을 처리하는 데 사용할 수있는 스레드 수가 줄어 듭니다. "


  1. Async / await는 스레드를 기반으로하지 않습니다. 비동기 처리를 기반으로합니다. ASP.NET에서 비동기 대기를 수행하면 요청 스레드가 스레드 풀로 반환되므로 비동기 작업이 완료 될 때까지 해당 요청을 처리하는 스레드 없습니다 . 요청 오버 헤드가 스레드 오버 헤드보다 낮기 때문에 이는 async / await가 스레드 풀보다 더 잘 확장 될 수 있음을 의미합니다.
  2. 요청은 뛰어난 비동기 작업의 수를 가지고있다. 이 개수는 .NET Framework의 ASP.NET 구현에 의해 관리됩니다 SynchronizationContext. 당신은에 대해 자세히 읽을 수 SynchronizationContext있는 내 MSDN 문서를 - 방법 ASP.NET의 그것을 커버 SynchronizationContext작동 방식 await사용 SynchronizationContext.

비동기 / 대기 전에 ASP.NET 비동기 처리가 가능했습니다. 비동기 페이지를 사용하고 WebClient(이벤트 기반 비동기 프로그래밍은를 기반으로하는 비동기 프로그래밍 스타일) 과 같은 EAP 구성 요소를 사용할 수 있습니다 SynchronizationContext. Async / await도 사용 SynchronizationContext하지만 훨씬 더 쉬운 구문이 있습니다.


스레드 풀을 작업 을 수행 하기 위해 고용 한 일련의 작업 자라고 상상해보십시오 . 당신의 노동자는 빠른 실행 의 CPU 에 대한 지침 귀하의 코드를.

이제 당신의 작업은 다른 느린 사람의 작업에 의존하게됩니다. 느린 사람은 디스크 또는 네트워크 입니다. 예를 들어, 작업은 두 부분으로 실행하는 한 부분이 있습니다 전에 느린 사람의 작업 및 실행하는 한 부분 느린 사람의 일을.

직원들에게 업무를 수행하도록 어떻게 조언 하시겠습니까? 각 작업자에게 "첫 번째 부분을 수행 한 다음 느린 사람이 끝날 때까지 기다린 다음 두 번째 부분을 수행하십시오"라고 말 하시겠습니까? 직원 모두가 느린 사람을 기다리고있는 것 같고 새로운 고객을 만족시킬 수 없기 때문에 직원 수를 늘리시겠습니까? 아니!

대신 각 작업자에게 첫 번째 부분을 수행하도록 요청하고 느린 사람에게 다시 와서 완료되면 대기열에 메시지를 삭제하도록 요청합니다. 각 작업자 (또는 작업자의 전용 하위 집합)에게 대기열에서 완료된 메시지를 찾고 작업의 두 번째 부분을 수행하도록 지시합니다.

스마트 커널 위에서 암시하는 속도가 느린 디스크 및 네트워크 IO 완료 메시지와 같은 큐를 유지하는 운영 체제 기능입니다.

참고 URL : https://stackoverflow.com/questions/9453560/why-use-async-requests-instead-of-using-a-larger-threadpool

반응형