dubbo原始碼-執行緒池分析

yiduwangkai發表於2016-09-09
dubbo預設提供了三種執行緒池,分別是
fixed 固定大小執行緒池,啟動時建立執行緒,不關閉,一直持有。
cached 快取執行緒池,空閒一分鐘自動刪除,需要時重建。
limited 可伸縮執行緒池,但池中的執行緒數只會增長不會收縮。(為避免收縮時突然來了大流量引起的效能問題)。

fixed:
public class FixedThreadPool implements ThreadPool {

public Executor getExecutor(URL url) {
String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);//Dubbo
int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS);//200
int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);//0
return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS,
queues == 0 ? new SynchronousQueue<Runnable>() :
(queues < 0 ? new LinkedBlockingQueue<Runnable>()
: new LinkedBlockingQueue<Runnable>(queues)),
new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url));
}
}

cached:
public class CachedThreadPool implements ThreadPool {

public Executor getExecutor(URL url) {
String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);//Dubbo
int cores = url.getParameter(Constants.CORE_THREADS_KEY, Constants.DEFAULT_CORE_THREADS);//0
int threads = url.getParameter(Constants.THREADS_KEY, Integer.MAX_VALUE);//Integer.MAX_VALUE
int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);//0
int alive = url.getParameter(Constants.ALIVE_KEY, Constants.DEFAULT_ALIVE);//60s
return new ThreadPoolExecutor(cores, threads, alive, TimeUnit.MILLISECONDS,
queues == 0 ? new SynchronousQueue<Runnable>() :
(queues < 0 ? new LinkedBlockingQueue<Runnable>()
: new LinkedBlockingQueue<Runnable>(queues)),
new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url));
}
}

limited:
public class LimitedThreadPool implements ThreadPool {

public Executor getExecutor(URL url) {
String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);//Dubbo
int cores = url.getParameter(Constants.CORE_THREADS_KEY, Constants.DEFAULT_CORE_THREADS);//0
int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS);//200
int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);//0
return new ThreadPoolExecutor(cores, threads, Long.MAX_VALUE, TimeUnit.MILLISECONDS,
queues == 0 ? new SynchronousQueue<Runnable>() :
(queues < 0 ? new LinkedBlockingQueue<Runnable>()
: new LinkedBlockingQueue<Runnable>(queues)),
new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url));
}
}

provider端:預設是fixed
consumer端:預設是cached
預設執行緒大小是200
AbortPolicyWithReport:
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
String msg = String.format("Thread pool is EXHAUSTED!" +
" Thread Name: %s, Pool Size: %d (active: %d, core: %d, max: %d, largest: %d), Task: %d (completed: %d)," +
" Executor status:(isShutdown:%s, isTerminated:%s, isTerminating:%s), in %s://%s:%d!" ,
threadName, e.getPoolSize(), e.getActiveCount(), e.getCorePoolSize(), e.getMaximumPoolSize(), e.getLargestPoolSize(),
e.getTaskCount(), e.getCompletedTaskCount(), e.isShutdown(), e.isTerminated(), e.isTerminating(),
url.getProtocol(), url.getIp(), url.getPort());
logger.warn(msg);
throw new RejectedExecutionException(msg);
}

可以通過如下更改:
<dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="100" />
<dubbo:provider threads="200" threadpool="fixed"/>
線上程中的執行緒被耗盡時出現如下錯誤:

[img]http://dl2.iteye.com/upload/attachment/0119/9408/e43659cd-2f77-3ba8-8040-da2dfe83f53a.png[/img]
解決方式:
1.通過jstack -l pid進行分析,檢視主要的鎖資源爭用情況,從而進行業務程式碼的排查
2.增大執行緒池的數量,預設是200
3.減小超時時間,避免業務處理時間過長,耗光所有的執行緒

相關文章