왜 프로그램 에 갑자기 200 개의 Dubbo-thread 스 레 드 가 추가 되 었 는 지 설명 합 니 다.
프로그램 스 레 드 스 택 정 보 를 볼 때 200 개의 Dubbo-thread 스 레 드 가 있 고 대부분 WAITING 상태 에 있 습 니 다.다음 과 같 습 니 다.
"Dubbo-thread-200" #160932 daemon prio=5 os_prio=0 tid=0x00007f5af9b54800 nid=0x79a6 waiting on condition [0x00007f5a9acd5000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000c78f1240> (a java.util.concurrent.SynchronousQueue$TransferStack)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:458)
at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:924)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
왜 이렇게 Dubbo-thread 라인 이 많 을까요?이 스 레 드 들 은 어떤 작용 을 합 니까?의문 을 가지 고 소스 코드 를 연구 했다.소스 코드 분석
Dubbo(2.7.5 버 전)의 스 레 드 풀 은 네 가지 구체 적 인 실현 유형 이 있다.
fixed=org.apache.dubbo.common.threadpool.support.fixed.FixedThreadPool
cached=org.apache.dubbo.common.threadpool.support.cached.CachedThreadPool
limited=org.apache.dubbo.common.threadpool.support.limited.LimitedThreadPool
eager=org.apache.dubbo.common.threadpool.support.eager.EagerThreadPool
프로그램 은 구체 적 인 구현 클래스 의 getExecutor(URL url)방법 을 호출 하여 스 레 드 풀 을 만 듭 니 다.이 방법 을 호출 하 는 것 은 DefaultExecutor Repository 류 의 createExecutor 방법 뿐 입 니 다.이 방법 은 url 의 매개 변수 threadpool=cached 에 따라 그러한 유형의 스 레 드 풀 을 만 들 기로 결 정 됩 니 다.createExecutor 는 개인 적 인 방법 으로 다음 두 가지 방법 이 있 습 니 다.
/**
* Get called when the server or client instance initiating.
*
* @param url
* @return
*/
public synchronized ExecutorService createExecutorIfAbsent(URL url) {
String componentKey = EXECUTOR_SERVICE_COMPONENT_KEY;
if (CONSUMER_SIDE.equalsIgnoreCase(url.getParameter(SIDE_KEY))) {
componentKey = CONSUMER_SIDE;
}
Map<Integer, ExecutorService> executors = data.computeIfAbsent(componentKey, k -> new ConcurrentHashMap<>());
Integer portKey = url.getPort();
ExecutorService executor = executors.computeIfAbsent(portKey, k -> createExecutor(url));
// If executor has been shut down, create a new one
if (executor.isShutdown() || executor.isTerminated()) {
executors.remove(portKey);
executor = createExecutor(url);
executors.put(portKey, executor);
}
return executor;
}
public ExecutorService getExecutor(URL url) {
String componentKey = EXECUTOR_SERVICE_COMPONENT_KEY;
if (CONSUMER_SIDE.equalsIgnoreCase(url.getParameter(SIDE_KEY))) {
componentKey = CONSUMER_SIDE;
}
Map<Integer, ExecutorService> executors = data.get(componentKey);
/**
* It's guaranteed that this method is called after {@link #createExecutorIfAbsent(URL)}, so data should already
* have Executor instances generated and stored.
*/
if (executors == null) {
logger.warn("No available executors, this is not expected, framework should call createExecutorIfAbsent first " +
"before coming to here.");
return null;
}
Integer portKey = url.getPort();
ExecutorService executor = executors.get(portKey);
if (executor != null) {
if (executor.isShutdown() || executor.isTerminated()) {
executors.remove(portKey);
executor = createExecutor(url);
executors.put(portKey, executor);
}
}
return executor;
}
위의 첫 번 째 방법 에 대해 비 고 는 서비스 제공 자 나 서비스 소비자 가 초기 화 할 때 호출 된다 는 것 을 설명 했다.debug 를 통 해 알 수 있 듯 이 서비스 제공 자 초기 화 는 스 레 드 이름 이 DubboServer Handler-10.12.16.67:20880-thread 인 스 레 드 탱크 를 만 들 고 서비스 소비 자 는 스 레 드 이름 이 DubboClient Handler-10.12.16.67:20880-thread 인 스 레 드 탱크 를 만 들 것 이다.Dubbo 가 만 든 스 레 드 탱크 는 Map 에 저장 되 어 공유 합 니 다.
private ConcurrentMap
밖의 키 는 서비스 제공 자 또는 소비 자 를 나타 낸다.안의 키 는 서비스 가 노출 된 포트 번 호 를 나타 낸다.즉,소비 자 는 같은 포트 번호 의 서비스 에 대해 하나의 스 레 드 탱크 만 만 만 들 고 같은 스 레 드 탱크 를 공유 하여 서비스 요청 과 정 보 를 받 은 후에 일련의 처 리 를 한다.
Dubbo-thread 이름과 달리 두 번 째 방법 으로 만 든 스 레 드 풀 일 가능성 이 높다.두 번 째 방법의 호출 은 위로 거 슬러 올 라 가면 비교적 분산 되 어 유용 한 정 보 를 찾 을 수 없다.
방법 에 대한 구체 적 인 내용 을 보면 이미 만 든 스 레 드 풀 이 닫 히 거나 종 료 될 때 새로운 스 레 드 풀 을 다시 만 듭 니 다.그 다음 에 어떤 상황 에서 오프라인 스 레 드 가 닫 히 거나 종 료 될 지 추측 했다.서비스 가 재 개 된 후에 스 택 정 보 를 출력 하 는 데 Dubbo-thread 스 레 드 가 없 었 다.그 다음 에 소비 자 와 공급 자 연결 이 끊 기 면 스 레 드 탱크 가 닫 히 지 않 을 까 추측 하여 서비스 제공 자 를 재 개 했다.과연 Dubbo-thread 스 레 드 를 재현 했다.
그리고 Dubbo 의 구체 적 인 스 레 드 탱크 생 성 방법 에 로 그 를 추가 하고 스 택 정 보 를 출력 합 니 다(이상 출력 호출 정 보 를 생 성 합 니 다).
다음 그림:
여기에 그림 설명 을 삽입 하면 channel 이 효력 을 잃 었 을 때 disconnected 방법 을 호출 하고 최종 적 으로 DefaultExecutor Repository 류 의 getExecutor 를 호출 하여 스 레 드 풀 을 만 듭 니 다.서비스 제공 자가 다시 시작 할 때 소비 자 는 해당 스 레 드 풀 을 shutdown 합 니 다.
스 레 드 풀 을 만 드 는 데 사용 되 는 URL 을 재현 하 는 것 은 Wrapped Channel Handler 클래스 의 URL 입 니 다.이 값 은 서비스 시작 초기 화 에 설정 되 어 있 으 며,AbstractClient 클 라 이언 트 Executor 보다 일찍 설정 되 어 있 습 니 다.
따라서 channel 이 끊 겨 서 다시 만 든 스 레 드 풀 에 사용 되 는 URL 과 클 라 이언 트 가 스 레 드 풀 을 처음 만 드 는 데 사용 하 는 URL 은 다 를 수 있 습 니 다.특히 consumer 의 스 레 드 풀 형식 을 설정 하지 않 았 을 때 초기 에 만 든 Cached 형식 스 레 드 풀,스 레 드 이름 은 DubboClient Handler 입 니 다.
사용 하 는 URL 을 다시 만 드 는 것 은 아래 방법 으로 설정 되 지 않 았 기 때문에 기본 형식 이 fixed 인 스 레 드 풀 을 만 들 것 입 니 다.스 레 드 수 는 기본 200 이 고 스 레 드 이름 은 Dubbo 입 니 다.
private void initExecutor(URL url) {
url = ExecutorUtil.setThreadName(url, CLIENT_THREAD_POOL_NAME);
url = url.addParameterIfAbsent(THREADPOOL_KEY, DEFAULT_CLIENT_THREADPOOL);
executor = executorRepository.createExecutorIfAbsent(url);
}
총결산그러면 Dubbo-thread 스 레 드 탱크 의 생 성 은 서비스 소비자 와 공급 자 간 의 연결 이 끊 겨 서 만 든 스 레 드 탱크 임 을 알 수 있 습 니 다.프로그램 이 초기 화 될 때 만 든 Dubbo Client Handler 스 레 드 탱크 를 대체 합 니 다.주로 channel 차단 후속 처 리 를 하고 서버 메 시 지 를 받 은 후의 반 직렬 화 등 작업 도 합 니 다.구체 적 인 것 은 ThreadlessExecutor(동기 호출 처리 류),Channel EventRunnable(channel 의 서로 다른 상태 처리,연결,메시지 수신,링크 차단 등 을 볼 수 있 습 니 다.
또 하 나 는 consumer.threadpool 형식,therads 등 정 보 를 설정 하지 않 으 면 연결 을 끊 고 만 든 스 레 드 풀 은 fixed 형식의 스 레 드 풀 이 고 스 레 드 수 는 기본 200 입 니 다.
이 프로그램 에 왜 갑자기 200 개의 Dubbo-thread 스 레 드 가 더 생 겼 는 지 에 대한 설명 은 바로 편집장 이 여러분 에 게 공유 한 모든 내용 입 니 다.참고 가 되 었 으 면 좋 겠 습 니 다.여러분 들 도 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
RPC 분산 서비스 프레임워크 - Dubbo 로드 밸런싱집단 부하가 균형적일 때 Dubbo는 다양한 균형 전략을 제공했는데 부족한 것은random 랜덤 호출.. 랜덤, 권중에 따라 랜덤 확률을 설정.. 한 단면에서 충돌할 확률이 높지만 호출량이 많을수록 분포가 고르고 확...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.