Alibaba 프로토콜은 스레드 풀을 수동으로 생성합니다. 왜 계속해서 Executor를 사용해야 합니까?

사전 공지

제목은 거창하다는 뜻이 아닙니다. 실제로 스레드 풀을 생성하기 위해 Executors를 사용하고 있습니다. 이 문서에서는 스레드 풀 매개변수, 스레드 상태 및 기타 개념에 대해 자세히 설명하지 않습니다.

나는 Alibaba가 스레드 풀을 수동으로 생성한 것의 깊은 의미를 알고 있지만 ThreadPoolExecutor를 통해 스레드 풀을 생성하면 사용자는 스레드 풀의 운영 규칙을 명확히 하고 리소스 고갈 위험을 피할 수 있습니다.

자원 고갈 위험

리소스 고갈의 위험은 주로 메모리로 인해 발생합니다.

1. Executors.newFixedThreadPool 및 Executors.newSingleThreadExecutor에 의해 생성된 스레드 풀을 사용하면 대기 대기열의 기본값은 Integer.MAX_VALUE이며 기본적으로 바인딩되지 않은 대기열과 동일합니다.

특히 집약적인 컴퓨팅 작업의 경우 스레드 수가 확실히 제한되어 있다는 것은 의심의 여지가 없습니다. 스레드 수를 너무 높게 설정하면 스레드 소비만 증가하고 작업 실행 효율성이 향상되지 않습니다. 요청량이 너무 많으면 큐에 많은 양의 요청 데이터가 쌓이게 되어 OOM이 발생할 가능성이 매우 높습니다.

2. Executors.newCachedThreadPool 및 Executors.newSingleThreadScheduledExecutor를 사용하여 생성된 스레드 풀의 경우 최대 스레드 수는 Integer.MAX_VALUE이며 이는 기본적으로 무한대와 동일합니다.

요청이 많고 스레드를 무제한으로 생성하는 경우 ThreadStackSize는 1024k로 계산되며 OOM이 발생할 가능성이 매우 높습니다.

스레드 풀을 생성하기 위해 실행자를 사용하는 이유는 무엇입니까?

두 가지 이유가 있습니다:

1. 온갖 규칙과 규정이 마음에 들지 않습니다. Java 생태계 자체를 포함하여 Java에는 이미 많은 규정이 있습니다. Ali의 또 다른 규정이 필요합니까?

2. Java에는 이러한 스레드 풀 도구가 포함되어 있으므로 유용할 것입니다.

개인적인 생각으로는 Executor를 사용하는 것과 ThreadPoolExecutor를 직접 사용하는 것 사이에는 본질적인 차이가 없으며, 작업 자체에 좀 더 주의를 기울여야 할 것 같습니다.

Executor를 사용하여 생성된 스레드 풀에 OOM이 있다고 가정하면 ThreadPoolExecutor를 사용하여 이를 방지할 수 있습니까? 대답은 '아니요'일 가능성이 높습니다.

스레드 풀 사용에 대한 몇 가지 고려 사항

나는 보통 다음 사항에 대해 생각하는 것부터 시작합니다.

1. 작업에 IO가 더 많나요, 아니면 컴퓨팅이 더 많나요?

2. 일반적으로 프로그램 스레드 풀은 소규모 및 다중 배치 작업을 처리하는 데 사용됩니다.

3. 스레드 수는 CPU 코어 수에 해당합니다.

4. 요청 금액과 요청 규모

5. 스레드 풀의 현재 실행 상태를 정기적으로 모니터링합니다.

6. 스레드 수를 동적으로 설정할 수 있습니다.

7. 적절한 수의 제어 스레드

8. 시간이 많이 걸리는 작업이라면 분할하거나 최적화해 보세요.

시나리오 가정

먼저 시나리오를 살펴보겠습니다. A가 규모 1억, 페이로드 100B의 데이터를 B에 계속 푸시한다고 가정하면, B가 데이터를 수신하고 응답한 후 A는 계속해서 B에 데이터를 푸시합니다. 데이터 푸시에 영향을 주지 않기 위해 B는 직접 응답한 다음 스레드 풀은 A가 푸시한 데이터를 비동기적으로 처리합니다.

어쩌면 가상의 시나리오는 다소 맛이 없을 수도 있지만 현실에도 그런 시나리오가 있으므로 그냥 해 보세요.

Executors.newFixedThreadPool을 사용하여 10개의 스레드로 스레드 풀을 생성한다고 가정하면 단일 스레드가 작업을 실행하는 데 10ms가 소요됩니다. 생각해보면 5분 후에 스레드 풀은 10 100 300개의 작업을 처리했습니다. 스레드 전환, 누적 프로세스 300,000 작업.

대기열에는 약 1억 개의 데이터가 남아 있습니다. 100B*100000000/1024, 약 9g의 데이터, 절대적으로 OOM입니다.

문제의 근본 원인

그렇다면 ThreadPoolExecutor를 사용할 때 얼마나 많은 스레드를 열어야 합니까?라는 질문이 생깁니다. 대기열은 얼마나 커야 합니까? 데이터가 오면 스레드가 가득 차고 큐도 가득 차서 데이터를 버리시겠습니까? 아니면 비즈니스 스레드 자체가 계속 실행됩니까?

이때 스레드는 기본적으로 너무 바빠서 CPU가 경주 중이고 메모리가 OOM 상태입니다.

현재 상황을 분석하고 문제를 해결합니다.

당연히 이때 무심코 스레드 풀에 제출하기보다는 속도를 줄여야 합니다.

위의 사항을 기반으로 이 프로그램 흐름을 다시 최적화해 보겠습니다.

1. 연산 집약적인 작업이므로 코어 4개, 스레드 10개를 사용하는 것이 합리적이며, 디버깅하기 전에 스레드 수를 동적으로 설정할 수 있습니다.

2. 전체 요청 크기는 약 10g이며, 8g 메모리를 사용하는 애플리케이션의 경우 1g 메모리와 약 10,000개의 작업 데이터를 점유하는 것을 고려합니다.

3. Executors.newSingleThreadScheduledExecutor를 사용하여 스레드 풀의 상태를 정기적으로 모니터링합니다.

위의 브레인리스 분석을 위해

1. Executors.newFixedThreadPool과 Executors.newSingleThreadScheduledExecutor를 사용하는데 전자는 작업을 실행하는 데 사용되고 후자는 정기적으로 스레드 풀 상태를 출력하는 데 사용됩니다.

2. B측은 A측과 협상하여 매번 1,000개의 데이터를 푸시하고, 10개의 스레드가 10,000개를 처리합니다. 세마포어는 데이터를 엄격하게 제어하기 위해 사용되며 데이터가 큐에 들어가지 않거나, 세마포어 제어를 사용합니다. , 큐는 최대 10,000개의 데이터만 입력할 수 있습니다. 세마포어의 크기는 10000개 이상의 스레드에 해당합니다.

3. 스레드 풀의 최대 스레드 수를 동적으로 설정하고 정기적으로 스레드 풀의 상태를 모니터링합니다. 마법은 없습니다. 스레드 풀은 이러한 방법을 제공합니다.

요약하다

이상은 본 글에서 자세히 설명하고자 하는 관점으로, 주로 다음과 같은 점을 표현하고자 한다.

1. 어떠한 규정도 맹목적으로 따르지 않는다

2. 비즈니스 데이터에 최대한 주의를 기울이세요

3. Thread Pool의 합리적인 활용

유익하셨다면 공감, 마음에 드셨다면 공감 부탁드립니다.

동명의 공개계좌 [코드농사밀]

Supongo que te gusta

Origin blog.csdn.net/weixin_43275277/article/details/125857510
Recomendado
Clasificación