Thread Pool2
순간적으로 많은 요청이 들어오는 경우 Thread Pool이 어떻게 동작하는지 알아보자.
Source code
https://github.com/teamsmiley/gitbook-sample/tree/main/ThreadTest
locust
locust -f locust.py --host http://localhost --users 1000 --spawn-rate 1000
source code
Console.WriteLine($"The number of processors on this computer is {Environment.ProcessorCount}.");
var maxWorkerThreads = 0;
var maxCompletionPortThreads = 0;
ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxCompletionPortThreads);
Console.WriteLine("Maximum worker threads: {0}", maxWorkerThreads);
var availableWorkerThreads = 0;
var completionPortThreads = 0;
ThreadPool.GetAvailableThreads(out availableWorkerThreads, out completionPortThreads);
Console.WriteLine($"Available Worker threads: {availableWorkerThreads}", availableWorkerThreads);
var usedWorkerThread = maxWorkerThreads - availableWorkerThreads;
Console.WriteLine($"Used worker threads: {usedWorkerThread}");
int minWorker, minIOC;
// Get the current settings.
ThreadPool.GetMinThreads(out minWorker, out minIOC);
Console.WriteLine("Minimum worker threads: {0}", minWorker);
// Thread.Sleep(1000 * 10); // Sleep for 10 seconds
Console.WriteLine("Thread completed. go back to the pool.");
return usedWorkerThread;
요청을 해보자.
1000개의 요청을 계속 보내도 Threadpool queue는 많이 늘어나지 않는다.

왜냐면 요청을 처리후 바로 다음 요청을 처리하기 때문이다.
이제 10초를 대기해보자.
Thread.Sleep(1000 * 10); // Sleep for 10 seconds
이부분의 주석을 제거하고 다시 실행

모든 요청이 큐로 들어가고 Thread가 하나씩 생성이 된다. 10초후에 요청 처리 완료된 Thread는 다시 pool로 들어가자마자 작업을 하므로 queue가 어느정도 늘어난후 상태를 유지한다.
문제 발생
2000개가 큐에 들어가고 초당 1-2개씩이 Thread가 생성이 되고 있다. 이것은 문제가 발생할수 있다.
Thread 생성가지만 1000초를 기다려야할수도 있다.
Threadpool 설정 변경
이제 Threadpool의 min설정을 변경해보자.
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ThreadPoolMinThreads>1000</ThreadPoolMinThreads> <!-- 이거 추가 -->
</PropertyGroup>
</Project>
다시 실행해보자.

minThreadworker가 1000개로 설정되있다
테스트해보자.

1000개의 쓰레드가 있으니 큐에 들어가지 않고 1초에 한개씩 생성이 되지 않고 모두 서비스에 사용할수 있다.
결론
갑자기 요청이 많은경우는 모니터링을 해가면서 queue가 60개 이상(모두 생성까지 모두 60초가 걸림) 이상이 되면 minThread를 늘리는것이 좋다.
더 중요한 결론
여기서는 cpu count는 별 문제가 안된다.
1개의 cpu는 1개의 minThread를 가지고 있고 12개의 cpu는 12개의 minThread를 가지고 있다.
요청이 많으면 1개나 12개나 큰 의미는 없다고 보여진다.
모니터링을 잘해보자.
docker exec -it threadtest-web-1 /tools/dotnet-counters monitor --process-id 1
더 더 중요한 결론
web api에서 요청을 받으면 모든걸 async로 처리해야한다. 특히 db query는 async로 처리해야한다. entity framework에서는 async method를 지원하므로 모두 그걸 사용하면 좋을거같다.
Last updated
Was this helpful?