@Override String formatInfo(ThreadPool.Info info) { return String.format( Locale.ROOT, "name [%s], core [%d], max [%d], keep alive [%s]", info.getName(), info.getMin(), info.getMax(), info.getKeepAlive()); }
public void testCorrectThreadPoolTypePermittedInSettings() throws InterruptedException { String threadPoolName = randomThreadPoolName(); ThreadPool.ThreadPoolType correctThreadPoolType = ThreadPool.THREAD_POOL_TYPES.get(threadPoolName); ThreadPool threadPool = null; try { threadPool = new ThreadPool( Settings.builder() .put("node.name", "testCorrectThreadPoolTypePermittedInSettings") .put("threadpool." + threadPoolName + ".type", correctThreadPoolType.getType()) .build()); ThreadPool.Info info = info(threadPool, threadPoolName); if (ThreadPool.Names.SAME.equals(threadPoolName)) { assertNull(info); // we don't report on the "same" threadpool } else { // otherwise check we have the expected type assertEquals(info.getThreadPoolType(), correctThreadPoolType); } } finally { terminateThreadPoolIfNeeded(threadPool); } }
public void testCustomThreadPool() throws Exception { ThreadPool threadPool = null; try { Settings nodeSettings = Settings.builder() .put("threadpool.my_pool1.type", "scaling") .put("threadpool.my_pool1.min", 1) .put( "threadpool.my_pool1.size", EsExecutors.boundedNumberOfProcessors(Settings.EMPTY)) .put("threadpool.my_pool1.keep_alive", "1m") .put("threadpool.my_pool2.type", "fixed") .put("threadpool.my_pool2.size", "1") .put("threadpool.my_pool2.queue_size", "1") .put("node.name", "testCustomThreadPool") .build(); threadPool = new ThreadPool(nodeSettings); ClusterSettings clusterSettings = new ClusterSettings(nodeSettings, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); threadPool.setClusterSettings(clusterSettings); ThreadPoolInfo groups = threadPool.info(); boolean foundPool1 = false; boolean foundPool2 = false; outer: for (ThreadPool.Info info : groups) { if ("my_pool1".equals(info.getName())) { foundPool1 = true; assertEquals(info.getThreadPoolType(), ThreadPool.ThreadPoolType.SCALING); } else if ("my_pool2".equals(info.getName())) { foundPool2 = true; assertEquals(info.getThreadPoolType(), ThreadPool.ThreadPoolType.FIXED); assertThat(info.getMin(), equalTo(1)); assertThat(info.getMax(), equalTo(1)); assertThat(info.getQueueSize().singles(), equalTo(1L)); } else { for (Field field : Names.class.getFields()) { if (info.getName().equalsIgnoreCase(field.getName())) { // This is ok it is a default thread pool continue outer; } } fail("Unexpected pool name: " + info.getName()); } } assertThat(foundPool1, is(true)); assertThat(foundPool2, is(true)); // Updating my_pool2 Settings settings = Settings.builder().put("threadpool.my_pool2.size", "10").build(); clusterSettings.applySettings(settings); groups = threadPool.info(); foundPool1 = false; foundPool2 = false; outer: for (ThreadPool.Info info : groups) { if ("my_pool1".equals(info.getName())) { foundPool1 = true; assertEquals(info.getThreadPoolType(), ThreadPool.ThreadPoolType.SCALING); } else if ("my_pool2".equals(info.getName())) { foundPool2 = true; assertThat(info.getMax(), equalTo(10)); assertThat(info.getMin(), equalTo(10)); assertThat(info.getQueueSize().singles(), equalTo(1L)); assertEquals(info.getThreadPoolType(), ThreadPool.ThreadPoolType.FIXED); } else { for (Field field : Names.class.getFields()) { if (info.getName().equalsIgnoreCase(field.getName())) { // This is ok it is a default thread pool continue outer; } } fail("Unexpected pool name: " + info.getName()); } } assertThat(foundPool1, is(true)); assertThat(foundPool2, is(true)); } finally { terminateThreadPoolIfNeeded(threadPool); } }
private Table buildTable( RestRequest req, ClusterStateResponse state, NodesInfoResponse nodesInfo, NodesStatsResponse nodesStats) { final String[] threadPools = req.paramAsStringArray("thread_pool_patterns", new String[] {"*"}); final DiscoveryNodes nodes = state.getState().nodes(); final Table table = getTableWithHeader(req); // collect all thread pool names that we see across the nodes final Set<String> candidates = new HashSet<>(); for (final NodeStats nodeStats : nodesStats.getNodes()) { for (final ThreadPoolStats.Stats threadPoolStats : nodeStats.getThreadPool()) { candidates.add(threadPoolStats.getName()); } } // collect all thread pool names that match the specified thread pool patterns final Set<String> included = new HashSet<>(); for (final String candidate : candidates) { if (Regex.simpleMatch(threadPools, candidate)) { included.add(candidate); } } for (final DiscoveryNode node : nodes) { final NodeInfo info = nodesInfo.getNodesMap().get(node.getId()); final NodeStats stats = nodesStats.getNodesMap().get(node.getId()); final Map<String, ThreadPoolStats.Stats> poolThreadStats; final Map<String, ThreadPool.Info> poolThreadInfo; if (stats == null) { poolThreadStats = Collections.emptyMap(); poolThreadInfo = Collections.emptyMap(); } else { // we use a sorted map to ensure that thread pools are sorted by name poolThreadStats = new TreeMap<>(); poolThreadInfo = new HashMap<>(); ThreadPoolStats threadPoolStats = stats.getThreadPool(); for (ThreadPoolStats.Stats threadPoolStat : threadPoolStats) { poolThreadStats.put(threadPoolStat.getName(), threadPoolStat); } if (info != null) { for (ThreadPool.Info threadPoolInfo : info.getThreadPool()) { poolThreadInfo.put(threadPoolInfo.getName(), threadPoolInfo); } } } for (Map.Entry<String, ThreadPoolStats.Stats> entry : poolThreadStats.entrySet()) { if (!included.contains(entry.getKey())) continue; table.startRow(); table.addCell(node.getName()); table.addCell(node.getId()); table.addCell(node.getEphemeralId()); table.addCell(info == null ? null : info.getProcess().getId()); table.addCell(node.getHostName()); table.addCell(node.getHostAddress()); table.addCell(node.getAddress().address().getPort()); final ThreadPoolStats.Stats poolStats = entry.getValue(); final ThreadPool.Info poolInfo = poolThreadInfo.get(entry.getKey()); Long maxQueueSize = null; String keepAlive = null; Integer minThreads = null; Integer maxThreads = null; if (poolInfo != null) { if (poolInfo.getQueueSize() != null) { maxQueueSize = poolInfo.getQueueSize().singles(); } if (poolInfo.getKeepAlive() != null) { keepAlive = poolInfo.getKeepAlive().toString(); } if (poolInfo.getMin() >= 0) { minThreads = poolInfo.getMin(); } if (poolInfo.getMax() >= 0) { maxThreads = poolInfo.getMax(); } } table.addCell(entry.getKey()); table.addCell(poolInfo == null ? null : poolInfo.getThreadPoolType().getType()); table.addCell(poolStats == null ? null : poolStats.getActive()); table.addCell(poolStats == null ? null : poolStats.getThreads()); table.addCell(poolStats == null ? null : poolStats.getQueue()); table.addCell(maxQueueSize); table.addCell(poolStats == null ? null : poolStats.getRejected()); table.addCell(poolStats == null ? null : poolStats.getLargest()); table.addCell(poolStats == null ? null : poolStats.getCompleted()); table.addCell(minThreads); table.addCell(maxThreads); table.addCell(keepAlive); table.endRow(); } } return table; }
@Test(timeout = 20000) public void testUpdatingThreadPoolSettings() throws Exception { internalCluster().startNodesAsync(2).get(); ThreadPool threadPool = internalCluster().getDataNodeInstance(ThreadPool.class); // Check that settings are changed assertThat( ((ThreadPoolExecutor) threadPool.executor(Names.SEARCH)).getKeepAliveTime(TimeUnit.MINUTES), equalTo(5L)); client() .admin() .cluster() .prepareUpdateSettings() .setTransientSettings(settingsBuilder().put("threadpool.search.keep_alive", "10m").build()) .execute() .actionGet(); assertThat( ((ThreadPoolExecutor) threadPool.executor(Names.SEARCH)).getKeepAliveTime(TimeUnit.MINUTES), equalTo(10L)); // Make sure that threads continue executing when executor is replaced final CyclicBarrier barrier = new CyclicBarrier(2); Executor oldExecutor = threadPool.executor(Names.SEARCH); threadPool .executor(Names.SEARCH) .execute( new Runnable() { @Override public void run() { try { barrier.await(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } catch (BrokenBarrierException ex) { // } } }); client() .admin() .cluster() .prepareUpdateSettings() .setTransientSettings(settingsBuilder().put("threadpool.search.type", "fixed").build()) .execute() .actionGet(); assertThat(threadPool.executor(Names.SEARCH), not(sameInstance(oldExecutor))); assertThat(((ThreadPoolExecutor) oldExecutor).isShutdown(), equalTo(true)); assertThat(((ThreadPoolExecutor) oldExecutor).isTerminating(), equalTo(true)); assertThat(((ThreadPoolExecutor) oldExecutor).isTerminated(), equalTo(false)); barrier.await(); // Make sure that new thread executor is functional threadPool .executor(Names.SEARCH) .execute( new Runnable() { @Override public void run() { try { barrier.await(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } catch (BrokenBarrierException ex) { // } } }); client() .admin() .cluster() .prepareUpdateSettings() .setTransientSettings(settingsBuilder().put("threadpool.search.type", "fixed").build()) .execute() .actionGet(); barrier.await(); Thread.sleep(200); // Check that node info is correct NodesInfoResponse nodesInfoResponse = client().admin().cluster().prepareNodesInfo().all().execute().actionGet(); for (int i = 0; i < 2; i++) { NodeInfo nodeInfo = nodesInfoResponse.getNodes()[i]; boolean found = false; for (ThreadPool.Info info : nodeInfo.getThreadPool()) { if (info.getName().equals(Names.SEARCH)) { assertThat(info.getType(), equalTo("fixed")); found = true; break; } } assertThat(found, equalTo(true)); Map<String, Object> poolMap = getPoolSettingsThroughJson(nodeInfo.getThreadPool(), Names.SEARCH); } }