programing

과부하 상태에서 스레드 풀 부족 문제 해결

telecom 2023. 6. 4. 10:18
반응형

과부하 상태에서 스레드 풀 부족 문제 해결

Dotnet-core(3.1) 응용 프로그램에서 높은 로드 문제가 발생했습니다.

일정 수준 이상의 연결(가상 사용자)이 발생하면 병목 현상이 발생하고 서버가 부족하며 요청 시간이 초과되지만 프로세스가 중단되지 않습니다(nokestrel 로그 없음).우리는 우리의 앱을 벤치마킹하기 위해 K6를 사용하고 있습니다.현재 로드 테스트는 로그인 페이지에서만 GET 요청을 수행하여 작은 데이터 세트(가입 없음 등)에서 기본 SQL 요청 하나를 트리거합니다.

Visual Studio 2019 Performance Profiler 툴과 perfview를 사용하여 문제를 조사했지만, 이러한 툴 중 어떤 것도 이러한 병목 현상을 일으키는 코드 부분을 식별하는 데 도움이 되지 않았습니다.

ThreadPool 기아에 대한 이 기사를 찾았습니다: https://learn.microsoft.com/fr-fr/archive/blogs/vancem/diagnosing-net-core-threadpool-starvation-with-perfview-why-my-service-is-not-saturating-all-cores-or-seems-to-stall 다음 예제와 같이 임의의 값으로 최소 ThreadPool을 조정하면,(그래프가 아닌) 성능이 크게 향상되었습니다.이건 스톱 갭 같은데, 사용하는 게 얼마나 나쁜가요?

System.Threading.ThreadPool.SetMinThreads(200, 200);

기아를 보여주는 벤치마크 설명 : 2C_2G/100.csv => 코어 2개, 2Go RAM, 가상 사용자 100명

환경:

  • 역방향 프록시로 nginx
  • K6을 벤치마크 툴
  • 닷넷 코어 3.1(엔티티 프레임워크 포함)
  • 운영 체제 : Ubuntu 20.04
  • mariadbas 데이터베이스

스레드 풀에 있는 동안 장기 실행 코드를 실행하고 있습니다.

이를 위한 방법은 다음과 같습니다.Task.Run:

public async Task<byte> CalculateChecksumAsync(Stream stream) => await Task.Run(() =>
{
    int i;
    byte checksum = 0;
    while ((i = stream.ReadByte()) >= 0)
    {
        checksum += (byte)i;
    }
    return checksum;
});

비동기/대기가 있기 때문에 완전히 비동기 코드처럼 보이는 일상적인 관찰자에게.Task온통.

그러나 실제로는 스트림을 읽는 데 걸리는 시간 동안 스레드 풀 스레드를 묶게 됩니다(데이터의 양뿐만 아니라 스트림의 대역폭에도 따라 다름).

스레드 풀이 부족하면 스레드 풀이 새 스레드를 생성할 때까지 1초의 지연이 발생합니다.그 말은 다음에 전화가 올 때까지Task.RunCPU가 유휴 상태인 경우에도 작업이 그만큼 지연됩니다.

대안:

  • 가능한 경우 동기식 방법 대신 비동기식 방법을 사용합니다(예:Stream.ReadAsync), 특히 스레드 풀에 있을
  • 코드에 대한 생성: 장기실코대장한기실작행생업성:
    public async Task<byte> CalculateChecksumAsync(Stream stream) => await Task.Factory.StartNew(() =>
    {
        int i;
        byte checksum = 0;
        while ((i = stream.ReadByte()) >= 0)
        {
            checksum += (byte)i;
        }
        return checksum;
    },
    TaskCreationOptions.LongRunning);
    

TaskCreationOptions.LongRunning플래그는 C#에게 작업을 위해 즉시 새 스레드가 생성되기를 원한다고 알려줍니다.

네, 최소 작업자 스레드 수를 늘리는 것이 해결책이 아니라 갭 스토퍼입니다.

당신은 그 문제를 재현할 수 있는 것 같습니다.그런 경우에는 다음을 사용할 것을 제안합니다.dotnet-dump차단 코드가 어디에 있는지 확인할 수 있습니다.이 YouTube 비디오의 스레드 풀 기아 진단 단계를 따르십시오. 꽤 효과적입니다.

BTW, 갭 스토퍼 코드의 경우, 문제를 일으키지 않는 비동기 IO 풀 카운트에 대한 두 번째 인수를 읽고 유지하며 호출의 설정 결과를 확인합니다.

int minWorker, minIOC;
// Get the current settings.
ThreadPool.GetMinThreads(out minWorker, out minIOC);
// Change the minimum number of worker threads to four, but
// keep the old setting for minimum asynchronous I/O 
// completion threads.
if (ThreadPool.SetMinThreads(200, minIOC))
{
    // The minimum number of threads was set successfully.
}
else
{
    // The minimum number of threads was not changed.
}

언급URL : https://stackoverflow.com/questions/73637676/troubleshoot-threadpool-starvation-under-heavy-load

반응형