线程池
线程池 | 线程池作用 |
---|---|
fixed | 固定大小线程池,启动时建立线程,不关闭,一直持有 |
cached | 缓存线程池,空闲一分钟自动删除,需要时重建 |
limited | 可伸缩线程池,但池中的线程数只会增加不会收缩 |
eager | 优先创建Worker线程池 |
线程配置
fixed: <dubbo:protocol name=“dubbo” port=“29014” dispatcher=“all” threadpool=“fixed” threadname=“jangzheng” threads=“200” queues=“0”/>
limited: <dubbo:protocol name=“dubbo” port=“29014” dispatcher=“all” threadpool=“limited” threadname=“jangzheng” corethreads=“10” threads=“200” queues=“0”/>
cached:<dubbo:protocol name=“dubbo” port=“29014” dispatcher=“all” threadpool=“cached” threadname=“jangzheng” corethreads=“10” threads=“200” queues=“0” alive=“60000”/>
eager:<dubbo:protocol name=“dubbo” port=“29014” dispatcher=“all” threadpool=“eager” threadname=“jangzheng” corethreads=“10” threads=“200” queues=“0” alive=“60000”/>
代码分析
FixedThreadPool
*/
//org.apache.dubbo.common.threadpool.support.fixed.FixedThreadPool
public class FixedThreadPool implements ThreadPool {
@Override
public Executor getExecutor(URL url) {
String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME);
int threads = url.getParameter(THREADS_KEY, DEFAULT_THREADS);
int queues = url.getParameter(QUEUES_KEY, DEFAULT_QUEUES);
return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS,
queues == 0 ? new SynchronousQueue<Runnable>() :
(queues < 0 ? new LinkedBlockingQueue<Runnable>()
: new LinkedBlockingQueue<Runnable>(queues)),
new NamedInternalThreadFactory(name, true), new AbortPolicyWithReport(name, url));
}
}
LimitedThreadPool
//org.apache.dubbo.common.threadpool.support.limited.LimitedThreadPool
public class LimitedThreadPool implements ThreadPool {
@Override
public Executor getExecutor(URL url) {
String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME);
int cores = url.getParameter(CORE_THREADS_KEY, DEFAULT_CORE_THREADS);
int threads = url.getParameter(THREADS_KEY, DEFAULT_THREADS);
int queues = url.getParameter(QUEUES_KEY, DEFAULT_QUEUES);
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 NamedInternalThreadFactory(name, true), new AbortPolicyWithReport(name, url));
}
}
CachedThreadPool
//org.apache.dubbo.common.threadpool.support.cached.CachedThreadPool
public class CachedThreadPool implements ThreadPool {
@Override
public Executor getExecutor(URL url) {
String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME);
int cores = url.getParameter(CORE_THREADS_KEY, DEFAULT_CORE_THREADS);
int threads = url.getParameter(THREADS_KEY, Integer.MAX_VALUE);
int queues = url.getParameter(QUEUES_KEY, DEFAULT_QUEUES);
int alive = url.getParameter(ALIVE_KEY, DEFAULT_ALIVE);
return new ThreadPoolExecutor(cores, threads, alive, TimeUnit.MILLISECONDS,
queues == 0 ? new SynchronousQueue<Runnable>() :
(queues < 0 ? new LinkedBlockingQueue<Runnable>()
: new LinkedBlockingQueue<Runnable>(queues)),
new NamedInternalThreadFactory(name, true), new AbortPolicyWithReport(name, url));
}
}
EagerThreadPool
//org.apache.dubbo.common.threadpool.support.eager.EagerThreadPool
public class EagerThreadPool implements ThreadPool {
@Override
public Executor getExecutor(URL url) {
String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME);
int cores = url.getParameter(CORE_THREADS_KEY, DEFAULT_CORE_THREADS);
int threads = url.getParameter(THREADS_KEY, Integer.MAX_VALUE);
int queues = url.getParameter(QUEUES_KEY, DEFAULT_QUEUES);
int alive = url.getParameter(ALIVE_KEY, DEFAULT_ALIVE);
// init queue and executor
TaskQueue<Runnable> taskQueue = new TaskQueue<Runnable>(queues <= 0 ? 1 : queues);
EagerThreadPoolExecutor executor = new EagerThreadPoolExecutor(cores,
threads,
alive,
TimeUnit.MILLISECONDS,
taskQueue,
new NamedInternalThreadFactory(name, true),
new AbortPolicyWithReport(name, url));
taskQueue.setExecutor(executor);
return executor;
}
}
引入时机
我们假设为All的线程模型,进入AllChannelHandler类中
//org.apache.dubbo.remoting.transport.dispatcher.all.AllChannelHandler#connected
@Override
public void connected(Channel channel) throws RemotingException {
//进入此方法,获取线程池
ExecutorService executor = getExecutorService();
try {
executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.CONNECTED));
} catch (Throwable t) {
throw new ExecutionException("connect event", channel, getClass() + " error when process connected event .", t);
}
}
//org.apache.dubbo.remoting.transport.dispatcher.WrappedChannelHandler#getExecutorService
@Deprecated
public ExecutorService getExecutorService() {
//进入此方法
return getSharedExecutorService();
}
//继续调用
public ExecutorService getSharedExecutorService() {
ExecutorRepository executorRepository =
//此处ExecutorRepository需要关注下
ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
ExecutorService executor = executorRepository.getExecutor(url);
if (executor == null) {
//通过url获取对应的线程池,我们此方法
executor = executorRepository.createExecutorIfAbsent(url);
}
return executor;
}
//org.apache.dubbo.common.threadpool.manager.DefaultExecutorRepository#createExecutorIfAbsent
public synchronized ExecutorService createExecutorIfAbsent(URL url) {
String componentKey = EXECUTOR_SERVICE_COMPONENT_KEY;
if (CONSUMER_SIDE.equalsIgnoreCase(url.getSide())) {
componentKey = CONSUMER_SIDE;
}
Map<Integer, ExecutorService> executors = data.computeIfAbsent(componentKey, k -> new ConcurrentHashMap<>());
Integer portKey = url.getPort();
//调用createExecutor(url),创建线程池,我们看下
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;
}
//org.apache.dubbo.common.threadpool.manager.DefaultExecutorRepository#createExecutor
private ExecutorService createExecutor(URL url) {
return (ExecutorService)
//创建指定的线程池,如果没有指定的话,默认使用fixed
ExtensionLoader.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url);
}
//org.apache.dubbo.common.threadpool.ThreadPool
@SPI("fixed")
public interface ThreadPool {
/**
* Thread pool
*
* @param url URL contains thread parameter
* @return thread pool
*/
@Adaptive({THREADPOOL_KEY}) //THREADPOOL_KEY = "threadpool";
Executor getExecutor(URL url);
}
线程数设置
QPS = 100 (每秒100个请求)
tp99 = 100ms (每个请求处理时间是100毫秒)
threads = QPS * tp99 / 1000 (QPS 乘上tp99得到每个请求处理的时间,除以1000 转为秒)