From d7bd99b3637ff905af32580e414cccceb1c4de58 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E6=88=90=E5=85=B4?=
<49221670+Createsequence@users.noreply.github.com>
Date: Tue, 22 Nov 2022 18:46:59 +0800
Subject: [PATCH 1/3] fix: The thread pool that is not managed by spring will
also be destroyed (#990) (#1003)
* fix: The thread pool that is not managed by spring will also be destroyed (#990)
* optimize code and comments
---
.../executor/DynamicThreadPoolExecutor.java | 29 +++++-
.../DynamicThreadPoolExecutorTest.java | 23 ++++-
.../DynamicThreadPoolAutoConfiguration.java | 7 ++
...AdaptedThreadPoolDestroyPostProcessor.java | 91 +++++++++++++++++++
4 files changed, 146 insertions(+), 4 deletions(-)
create mode 100644 hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/support/AdaptedThreadPoolDestroyPostProcessor.java
diff --git a/hippo4j-core/src/main/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutor.java b/hippo4j-core/src/main/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutor.java
index 011e4148..a33c6b83 100644
--- a/hippo4j-core/src/main/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutor.java
+++ b/hippo4j-core/src/main/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutor.java
@@ -37,6 +37,7 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
/**
@@ -45,6 +46,12 @@ import java.util.concurrent.atomic.AtomicLong;
@Slf4j
public class DynamicThreadPoolExecutor extends ExtensibleThreadPoolExecutor implements DisposableBean {
+ /**
+ * A flag used to indicate whether destroy() method has been called,
+ * after the flag is set to false, calling destroy() method again will not take effect
+ */
+ private final AtomicBoolean active;
+
/**
* Wait for tasks to complete on shutdown
*/
@@ -92,11 +99,22 @@ public class DynamicThreadPoolExecutor extends ExtensibleThreadPoolExecutor impl
threadPoolId, new DefaultThreadPoolPluginManager().setPluginComparator(AnnotationAwareOrderComparator.INSTANCE),
corePoolSize, maximumPoolSize, keepAliveTime, unit,
blockingQueue, threadFactory, rejectedExecutionHandler);
- log.info("Initializing ExecutorService {}", threadPoolId);
+ log.info("Initializing ExecutorService '{}'", threadPoolId);
this.waitForTasksToCompleteOnShutdown = waitForTasksToCompleteOnShutdown;
// Init default plugins.
new DefaultThreadPoolPluginRegistrar(executeTimeOut, awaitTerminationMillis)
.doRegister(this);
+ this.active = new AtomicBoolean(true);
+ }
+
+ /**
+ *
Whether the current instance is in the active state.
+ * It returns false when the xx method is called at least once.
+ *
+ * @return true if current instance is in the active state, false otherwise
+ */
+ public boolean isActive() {
+ return active.get();
}
/**
@@ -104,12 +122,21 @@ public class DynamicThreadPoolExecutor extends ExtensibleThreadPoolExecutor impl
*/
@Override
public void destroy() {
+ // instance has been destroyed, not need to call this method again
+ if (!isActive()) {
+ log.warn("Failed to destroy ExecutorService '{}' because it has already been destroyed", getThreadPoolId());
+ return;
+ }
if (isWaitForTasksToCompleteOnShutdown()) {
super.shutdown();
} else {
super.shutdownNow();
}
getThreadPoolPluginManager().clear();
+ log.info("ExecutorService '{}' has been destroyed", getThreadPoolId());
+
+ // modify the flag to false avoid the method being called repeatedly
+ active.set(false);
}
/**
diff --git a/hippo4j-core/src/test/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutorTest.java b/hippo4j-core/src/test/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutorTest.java
index 63d362af..275cd915 100644
--- a/hippo4j-core/src/test/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutorTest.java
+++ b/hippo4j-core/src/test/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutorTest.java
@@ -95,7 +95,7 @@ public class DynamicThreadPoolExecutorTest {
});
executor.destroy();
- // waitting for terminated
+ // waiting for terminated
while (!executor.isTerminated()) {
} ;
Assert.assertEquals(2, count.get());
@@ -119,9 +119,9 @@ public class DynamicThreadPoolExecutorTest {
});
executor.destroy();
- // waitting for terminated
+ // waiting for terminated
while (!executor.isTerminated()) {
- } ;
+ }
Assert.assertEquals(1, count.get());
}
@@ -157,4 +157,21 @@ public class DynamicThreadPoolExecutorTest {
Assert.assertFalse(executor.isWaitForTasksToCompleteOnShutdown());
}
+ @Test
+ public void testIsActive() {
+ DynamicThreadPoolExecutor executor = new DynamicThreadPoolExecutor(
+ 1, 1, 1000L, TimeUnit.MILLISECONDS,
+ 1000L, true, 1000L,
+ new ArrayBlockingQueue<>(1), "test", Thread::new, new ThreadPoolExecutor.DiscardOldestPolicy());
+ Assert.assertTrue(executor.isActive());
+
+ // waiting for terminated
+ executor.destroy();
+ while (!executor.isTerminated()) {
+ }
+ Assert.assertFalse(executor.isActive());
+ executor.destroy();
+ Assert.assertFalse(executor.isActive());
+ }
+
}
diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java
index 8614c4fc..c271fac4 100644
--- a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java
+++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java
@@ -57,6 +57,7 @@ import cn.hippo4j.springboot.starter.remote.HttpAgent;
import cn.hippo4j.springboot.starter.remote.HttpScheduledHealthCheck;
import cn.hippo4j.springboot.starter.remote.ServerHealthCheck;
import cn.hippo4j.springboot.starter.remote.ServerHttpAgent;
+import cn.hippo4j.springboot.starter.support.AdaptedThreadPoolDestroyPostProcessor;
import cn.hippo4j.springboot.starter.support.DynamicThreadPoolConfigService;
import cn.hippo4j.springboot.starter.support.DynamicThreadPoolPostProcessor;
import cn.hippo4j.springboot.starter.support.ThreadPoolPluginRegisterPostProcessor;
@@ -68,6 +69,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.info.BuildProperties;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
@@ -120,6 +122,11 @@ public class DynamicThreadPoolAutoConfiguration {
return new DynamicThreadPoolConfigService(httpAgent, properties, notifyConfigBuilder, hippo4jBaseSendMessageService, dynamicThreadPoolSubscribeConfig);
}
+ @Bean
+ public AdaptedThreadPoolDestroyPostProcessor adaptedThreadPoolDestroyPostProcessor(ApplicationContext applicationContext) {
+ return new AdaptedThreadPoolDestroyPostProcessor(applicationContext);
+ }
+
@Bean
@SuppressWarnings("all")
public DynamicThreadPoolPostProcessor threadPoolBeanPostProcessor(HttpAgent httpAgent,
diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/support/AdaptedThreadPoolDestroyPostProcessor.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/support/AdaptedThreadPoolDestroyPostProcessor.java
new file mode 100644
index 00000000..61b8418d
--- /dev/null
+++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/support/AdaptedThreadPoolDestroyPostProcessor.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package cn.hippo4j.springboot.starter.support;
+
+import cn.hippo4j.core.executor.DynamicThreadPoolExecutor;
+import cn.hippo4j.core.executor.DynamicThreadPoolWrapper;
+import cn.hippo4j.core.executor.manage.GlobalThreadPoolManage;
+import cn.hippo4j.core.executor.support.adpter.DynamicThreadPoolAdapter;
+import cn.hippo4j.core.executor.support.adpter.DynamicThreadPoolAdapterChoose;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
+import org.springframework.context.ApplicationContext;
+
+import java.util.Optional;
+
+/**
+ *
Adapted thread pool destroy post processor.
+ * The processor is used to destroy the internal {@link DynamicThreadPoolExecutor} instance
+ * in the instance adapted by {@link DynamicThreadPoolAdapter} in the spring context.
+ *
+ * @see DynamicThreadPoolAdapter
+ */
+@RequiredArgsConstructor
+@Slf4j
+public class AdaptedThreadPoolDestroyPostProcessor implements DestructionAwareBeanPostProcessor {
+
+ /**
+ * Application context.
+ */
+ private final ApplicationContext applicationContext;
+
+ /**
+ * If {@link DynamicThreadPoolAdapterChoose#match} method returns true,
+ * try to destroy its internal {@link DynamicThreadPoolExecutor} instance.
+ *
+ * @param bean the bean instance to check
+ * @return {@code true} if {@link DynamicThreadPoolAdapterChoose#match} method returns true, false otherwise
+ * @see DynamicThreadPoolAdapterChoose#match
+ */
+ @Override
+ public boolean requiresDestruction(Object bean) {
+ return DynamicThreadPoolAdapterChoose.match(bean);
+ }
+
+ /**
+ * If the internal {@link DynamicThreadPoolExecutor} instance in the adapted bean is not managed by spring,
+ * call its {@link DynamicThreadPoolExecutor#destroy()} directly.
+ *
+ * @param bean the bean instance to be destroyed
+ * @param beanName the name of the bean
+ * @throws BeansException in case of errors
+ * @see DynamicThreadPoolExecutor#destroy()
+ */
+ @Override
+ public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
+ Optional.ofNullable(DynamicThreadPoolAdapterChoose.unwrap(bean))
+ .map(DynamicThreadPoolExecutor::getThreadPoolId)
+ // the internal thread pool is also managed by spring, no manual destruction required
+ .filter(applicationContext::containsBeanDefinition)
+ .map(GlobalThreadPoolManage::getExecutorService)
+ .ifPresent(executor -> destroyAdaptedThreadPoolExecutor(beanName, executor));
+ }
+
+ private void destroyAdaptedThreadPoolExecutor(String beanName, DynamicThreadPoolWrapper executor) {
+ try {
+ if (log.isDebugEnabled()) {
+ log.debug("Destroy internal dynamic thread pool '{}' for bean '{}'", executor.getThreadPoolId(), beanName);
+ }
+ executor.destroy();
+ } catch (Exception e) {
+ log.warn("Failed to destroy internal dynamic thread pool '{}' for bean '{}'", executor.getThreadPoolId(), beanName);
+ }
+ }
+}
From 196238b28f331882a88bba8c574a27ab65f553b9 Mon Sep 17 00:00:00 2001
From: atomFix <43168451+atomFix@users.noreply.github.com>
Date: Tue, 22 Nov 2022 18:54:49 +0800
Subject: [PATCH 2/3] completed #728 (#1005)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* unit test: ExecutorFactoryTest 补充测试用例 #728
* unit test #728 : format of normative notes
* unit test #728 : format of normative notes to En; eliminate the impact of common objects on the current test flow in other scenarios.
Co-authored-by: liukairong1
---
.../common/executor/ExecutorFactoryTest.java | 69 +++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/executor/ExecutorFactoryTest.java b/hippo4j-common/src/test/java/cn/hippo4j/common/executor/ExecutorFactoryTest.java
index 8cd8e010..f25e3721 100644
--- a/hippo4j-common/src/test/java/cn/hippo4j/common/executor/ExecutorFactoryTest.java
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/executor/ExecutorFactoryTest.java
@@ -17,5 +17,74 @@
package cn.hippo4j.common.executor;
+import cn.hippo4j.common.design.builder.ThreadFactoryBuilder;
+import cn.hippo4j.common.toolkit.MapUtil;
+import cn.hippo4j.common.toolkit.ReflectUtil;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.stream.IntStream;
+
public final class ExecutorFactoryTest {
+
+ ThreadFactory threadFactory = new ThreadFactoryBuilder().prefix("test").build();
+
+ /**
+ * data range min
+ */
+ Integer rangeMin = 1;
+ /**
+ * data range max
+ */
+ Integer rangeMax = 10;
+ /**
+ * default test index
+ */
+ Integer defaultIndex = 0;
+
+ @Test
+ public void assertNewSingleScheduledExecutorService() {
+ // init data snapshot
+ ThreadPoolManager poolManager = (ThreadPoolManager) ReflectUtil.getFieldValue(ExecutorFactory.Managed.class, "THREAD_POOL_MANAGER");
+ String poolName = (String) ReflectUtil.getFieldValue(ExecutorFactory.Managed.class, "DEFAULT_NAMESPACE");
+ Map>> manager = (Map>>) ReflectUtil.getFieldValue(poolManager, "resourcesManager");
+ Map> initRelationMap = manager.get(poolName);
+ int defaultManagerSize = manager.size();
+ int defaultRelationSize = MapUtil.isEmpty(initRelationMap) ? 0 : initRelationMap.size();
+
+ // test begin
+ ScheduledExecutorService executorService = ExecutorFactory.Managed.newSingleScheduledExecutorService(String.format("test-group-%s", defaultIndex), threadFactory);
+
+ Assert.assertNotNull(executorService);
+
+ // check default init
+ Assert.assertEquals(1, manager.size() - defaultManagerSize);
+
+ // check multiple registrations and check to see if it is still an instance
+ IntStream.rangeClosed(rangeMin, rangeMax).forEach(index -> ExecutorFactory.Managed.newSingleScheduledExecutorService(String.format("test-group-%s", index), threadFactory));
+ Assert.assertEquals(1, manager.size() - defaultManagerSize);
+
+ // check group size
+ Map> relationMap = manager.get(poolName);
+ Assert.assertEquals(11, relationMap.size() - defaultRelationSize);
+ // check the number of threads between the group and the thread pool
+ IntStream.rangeClosed(rangeMin, rangeMax).forEach(index -> {
+ String relationKey = String.format("test-group-%s", index);
+ Assert.assertNotNull(relationMap.get(relationKey));
+ Assert.assertEquals(1, relationMap.get(relationKey).size());
+ });
+
+ // instantiate the same group a second time and check the corresponding quantitative relationship
+ IntStream.rangeClosed(defaultIndex, rangeMax).forEach(index -> ExecutorFactory.Managed.newSingleScheduledExecutorService(String.format("test-group-%s", index), threadFactory));
+ // chek group size
+ Assert.assertEquals(11, manager.get(poolName).size() - defaultRelationSize);
+ // check the number of threads between the group and the thread pool
+ IntStream.rangeClosed(rangeMin, rangeMax).forEach(index -> Assert.assertEquals(2, relationMap.get(String.format("test-group-%s", index)).size()));
+ }
+
}
From b5b959c80bd877dd225e332aa78c79f413ac6394 Mon Sep 17 00:00:00 2001
From: "chen.ma"
Date: Tue, 22 Nov 2022 21:07:15 +0800
Subject: [PATCH 3/3] Code logic update
---
.github/FUNDING.yml | 2 +-
.../server/hippo4j-server-monitor.md | 10 ++++++++++
docs/docusaurus.config.js | 2 +-
.../server/hippo4j-server-monitor.md | 10 ++++++++++
.../server/hippo4j-server-monitor.md | 10 ++++++++++
.../server/hippo4j-server-monitor.md | 10 ++++++++++
.../platform/DingSendMessageHandler.java | 19 ++++++++++++++-----
.../DynamicThreadPoolAutoConfiguration.java | 8 ++++----
...ava => ConfigModeNotifyConfigBuilder.java} | 4 ++--
.../DynamicThreadPoolRefreshListener.java | 8 ++++----
.../event/PlatformsRefreshListener.java | 4 ++--
.../DynamicThreadPoolAutoConfiguration.java | 8 ++++----
...ava => ServerModeNotifyConfigBuilder.java} | 4 ++--
.../DynamicThreadPoolConfigService.java | 6 +++---
14 files changed, 77 insertions(+), 28 deletions(-)
rename hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/notify/{CoreNotifyConfigBuilder.java => ConfigModeNotifyConfigBuilder.java} (98%)
rename hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/notify/{ServerNotifyConfigBuilder.java => ServerModeNotifyConfigBuilder.java} (97%)
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index eb15bc5e..6e54c6c7 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,3 +1,3 @@
# These are supported funding model platforms
-custom: ['https://hippo4j.cn/docs/community/sponsor']
+custom: ['https://hippo4j.cn/community/sponsor']
diff --git a/docs/docs/user_docs/getting_started/server/hippo4j-server-monitor.md b/docs/docs/user_docs/getting_started/server/hippo4j-server-monitor.md
index b743c790..4a81a47b 100644
--- a/docs/docs/user_docs/getting_started/server/hippo4j-server-monitor.md
+++ b/docs/docs/user_docs/getting_started/server/hippo4j-server-monitor.md
@@ -47,6 +47,16 @@ spring:
thread-pool-types: dynamic # 采集线程池的类型。eg:dynamic、web、adapter。可任意配置,默认 dynamic
```
+如果使用 `micrometer` 类型的监控指标,需要添加以下依赖。
+
+```xml
+
+ cn.hippo4j
+ hippo4j-spring-boot-starter-monitor-micrometer
+ 1.4.3-upgrade
+
+```
+
项目启动,访问 `http://localhost:29999/actuator/prometheus` 出现 `dynamic_thread_pool_` 前缀的指标,即为成功。

diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js
index 7c38db7b..8ff7a975 100644
--- a/docs/docusaurus.config.js
+++ b/docs/docusaurus.config.js
@@ -116,7 +116,7 @@ const config = {
},
{
href: 'https://xiaomage.info/knowledge-planet',
- label: '🥇代码实战课',
+ label: '知识星球',
position: 'left',
},
{
diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/current/user_docs/getting_started/server/hippo4j-server-monitor.md b/docs/i18n/zh/docusaurus-plugin-content-docs/current/user_docs/getting_started/server/hippo4j-server-monitor.md
index b743c790..4a81a47b 100644
--- a/docs/i18n/zh/docusaurus-plugin-content-docs/current/user_docs/getting_started/server/hippo4j-server-monitor.md
+++ b/docs/i18n/zh/docusaurus-plugin-content-docs/current/user_docs/getting_started/server/hippo4j-server-monitor.md
@@ -47,6 +47,16 @@ spring:
thread-pool-types: dynamic # 采集线程池的类型。eg:dynamic、web、adapter。可任意配置,默认 dynamic
```
+如果使用 `micrometer` 类型的监控指标,需要添加以下依赖。
+
+```xml
+
+ cn.hippo4j
+ hippo4j-spring-boot-starter-monitor-micrometer
+ 1.4.3-upgrade
+
+```
+
项目启动,访问 `http://localhost:29999/actuator/prometheus` 出现 `dynamic_thread_pool_` 前缀的指标,即为成功。

diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-1.4.3/user_docs/getting_started/server/hippo4j-server-monitor.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-1.4.3/user_docs/getting_started/server/hippo4j-server-monitor.md
index b743c790..4a81a47b 100644
--- a/docs/i18n/zh/docusaurus-plugin-content-docs/version-1.4.3/user_docs/getting_started/server/hippo4j-server-monitor.md
+++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-1.4.3/user_docs/getting_started/server/hippo4j-server-monitor.md
@@ -47,6 +47,16 @@ spring:
thread-pool-types: dynamic # 采集线程池的类型。eg:dynamic、web、adapter。可任意配置,默认 dynamic
```
+如果使用 `micrometer` 类型的监控指标,需要添加以下依赖。
+
+```xml
+
+ cn.hippo4j
+ hippo4j-spring-boot-starter-monitor-micrometer
+ 1.4.3-upgrade
+
+```
+
项目启动,访问 `http://localhost:29999/actuator/prometheus` 出现 `dynamic_thread_pool_` 前缀的指标,即为成功。

diff --git a/docs/versioned_docs/version-1.4.3/user_docs/getting_started/server/hippo4j-server-monitor.md b/docs/versioned_docs/version-1.4.3/user_docs/getting_started/server/hippo4j-server-monitor.md
index b743c790..4a81a47b 100644
--- a/docs/versioned_docs/version-1.4.3/user_docs/getting_started/server/hippo4j-server-monitor.md
+++ b/docs/versioned_docs/version-1.4.3/user_docs/getting_started/server/hippo4j-server-monitor.md
@@ -47,6 +47,16 @@ spring:
thread-pool-types: dynamic # 采集线程池的类型。eg:dynamic、web、adapter。可任意配置,默认 dynamic
```
+如果使用 `micrometer` 类型的监控指标,需要添加以下依赖。
+
+```xml
+
+ cn.hippo4j
+ hippo4j-spring-boot-starter-monitor-micrometer
+ 1.4.3-upgrade
+
+```
+
项目启动,访问 `http://localhost:29999/actuator/prometheus` 出现 `dynamic_thread_pool_` 前缀的指标,即为成功。

diff --git a/hippo4j-message/src/main/java/cn/hippo4j/message/platform/DingSendMessageHandler.java b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/DingSendMessageHandler.java
index a8329e07..e7c078e3 100644
--- a/hippo4j-message/src/main/java/cn/hippo4j/message/platform/DingSendMessageHandler.java
+++ b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/DingSendMessageHandler.java
@@ -92,13 +92,11 @@ public class DingSendMessageHandler extends AbstractRobotSendMessageHandler {
String title = Objects.equals(notifyConfig.getType(), "CONFIG") ? DING_NOTICE_TITLE : DING_ALARM_TITLE;
String text = robotMessageExecuteDTO.getText();
ArrayList atMobiles = CollectionUtil.newArrayList(notifyConfig.getReceives().split(","));
-
HashMap markdown = new HashMap<>();
markdown.put("title", title);
markdown.put("text", text);
HashMap at = new HashMap<>();
at.put("atMobiles", atMobiles);
-
HashMap markdownJson = new HashMap<>();
markdownJson.put("msgtype", "markdown");
markdownJson.put("markdown", markdown);
@@ -106,18 +104,29 @@ public class DingSendMessageHandler extends AbstractRobotSendMessageHandler {
try {
String responseBody = HttpUtil.post(serverUrl, markdownJson);
DingRobotResponse response = JSONUtil.parseObject(responseBody, DingRobotResponse.class);
- Assert.isTrue(response != null, "response is null");
+ Assert.isTrue(response != null, "Response is null.");
if (response.getErrcode() != 0) {
- log.error("Ding failed to send message,reason : {}", response.errmsg);
+ log.error("Ding failed to send message, reason : {}", response.errmsg);
}
} catch (Exception ex) {
- log.error("Ding failed to send message", ex);
+ log.error("Ding failed to send message.", ex);
}
}
+ /**
+ * Ding robot response.
+ */
@Data
static class DingRobotResponse {
+
+ /**
+ * Error code
+ */
private Long errcode;
+
+ /**
+ * Error message
+ */
private String errmsg;
}
}
diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java
index 51edf16c..62467060 100644
--- a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java
+++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java
@@ -21,7 +21,7 @@ import cn.hippo4j.common.api.ThreadPoolCheckAlarm;
import cn.hippo4j.common.api.ThreadPoolConfigChange;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.config.springboot.starter.monitor.ThreadPoolMonitorExecutor;
-import cn.hippo4j.config.springboot.starter.notify.CoreNotifyConfigBuilder;
+import cn.hippo4j.config.springboot.starter.notify.ConfigModeNotifyConfigBuilder;
import cn.hippo4j.config.springboot.starter.refresher.event.AdapterExecutorsRefreshListener;
import cn.hippo4j.config.springboot.starter.refresher.event.DynamicThreadPoolRefreshListener;
import cn.hippo4j.config.springboot.starter.refresher.event.PlatformsRefreshListener;
@@ -77,7 +77,7 @@ public class DynamicThreadPoolAutoConfiguration {
@Bean
public NotifyConfigBuilder notifyConfigBuilder(AlarmControlHandler alarmControlHandler) {
- return new CoreNotifyConfigBuilder(alarmControlHandler, bootstrapConfigProperties);
+ return new ConfigModeNotifyConfigBuilder(alarmControlHandler, bootstrapConfigProperties);
}
@Bean
@@ -105,9 +105,9 @@ public class DynamicThreadPoolAutoConfiguration {
@Bean
@SuppressWarnings("all")
public DynamicThreadPoolRefreshListener hippo4jExecutorsListener(ThreadPoolConfigChange threadPoolConfigChange,
- CoreNotifyConfigBuilder coreNotifyConfigBuilder,
+ ConfigModeNotifyConfigBuilder configModeNotifyConfigBuilder,
Hippo4jBaseSendMessageService hippoBaseSendMessageService) {
- return new DynamicThreadPoolRefreshListener(threadPoolConfigChange, coreNotifyConfigBuilder, hippoBaseSendMessageService);
+ return new DynamicThreadPoolRefreshListener(threadPoolConfigChange, configModeNotifyConfigBuilder, hippoBaseSendMessageService);
}
@Bean
diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/notify/CoreNotifyConfigBuilder.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/notify/ConfigModeNotifyConfigBuilder.java
similarity index 98%
rename from hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/notify/CoreNotifyConfigBuilder.java
rename to hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/notify/ConfigModeNotifyConfigBuilder.java
index 9dba54a8..7a01ae4e 100644
--- a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/notify/CoreNotifyConfigBuilder.java
+++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/notify/ConfigModeNotifyConfigBuilder.java
@@ -32,11 +32,11 @@ import java.util.*;
import java.util.stream.Collectors;
/**
- * Core notify config builder.
+ * Config mode notify config builder.
*/
@AllArgsConstructor
@Slf4j
-public class CoreNotifyConfigBuilder implements NotifyConfigBuilder {
+public class ConfigModeNotifyConfigBuilder implements NotifyConfigBuilder {
private final AlarmControlHandler alarmControlHandler;
diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/event/DynamicThreadPoolRefreshListener.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/event/DynamicThreadPoolRefreshListener.java
index fe30533c..4ed28af4 100644
--- a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/event/DynamicThreadPoolRefreshListener.java
+++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/event/DynamicThreadPoolRefreshListener.java
@@ -24,7 +24,7 @@ import cn.hippo4j.common.executor.support.ResizableCapacityLinkedBlockingQueue;
import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.config.springboot.starter.config.BootstrapConfigProperties;
import cn.hippo4j.config.springboot.starter.config.ExecutorProperties;
-import cn.hippo4j.config.springboot.starter.notify.CoreNotifyConfigBuilder;
+import cn.hippo4j.config.springboot.starter.notify.ConfigModeNotifyConfigBuilder;
import cn.hippo4j.config.springboot.starter.support.GlobalCoreThreadPoolManage;
import cn.hippo4j.core.executor.DynamicThreadPoolExecutor;
import cn.hippo4j.core.executor.manage.GlobalThreadPoolManage;
@@ -60,7 +60,7 @@ public class DynamicThreadPoolRefreshListener extends AbstractRefreshListener changeKeys = new ArrayList<>();
- Map> newDynamicThreadPoolNotifyMap = coreNotifyConfigBuilder.buildSingleNotifyConfig(executorProperties);
+ Map> newDynamicThreadPoolNotifyMap = configModeNotifyConfigBuilder.buildSingleNotifyConfig(executorProperties);
Map> notifyConfigs = hippo4jBaseSendMessageService.getNotifyConfigs();
if (CollectionUtil.isNotEmpty(notifyConfigs)) {
for (Map.Entry> each : newDynamicThreadPoolNotifyMap.entrySet()) {
@@ -183,7 +183,7 @@ public class DynamicThreadPoolRefreshListener extends AbstractRefreshListener> notifyConfig = configBuilder.buildSingleNotifyConfig(executorProperties);
sendMessageService.putPlatform(notifyConfig);
wrapper.setInitFlag(Boolean.TRUE);
diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java
index c271fac4..2650fb11 100644
--- a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java
+++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/config/DynamicThreadPoolAutoConfiguration.java
@@ -52,7 +52,7 @@ import cn.hippo4j.springboot.starter.monitor.ReportingEventExecutor;
import cn.hippo4j.springboot.starter.monitor.collect.RunTimeInfoCollector;
import cn.hippo4j.springboot.starter.monitor.send.MessageSender;
import cn.hippo4j.springboot.starter.monitor.send.http.HttpConnectSender;
-import cn.hippo4j.springboot.starter.notify.ServerNotifyConfigBuilder;
+import cn.hippo4j.springboot.starter.notify.ServerModeNotifyConfigBuilder;
import cn.hippo4j.springboot.starter.remote.HttpAgent;
import cn.hippo4j.springboot.starter.remote.HttpScheduledHealthCheck;
import cn.hippo4j.springboot.starter.remote.ServerHealthCheck;
@@ -116,10 +116,10 @@ public class DynamicThreadPoolAutoConfiguration {
@SuppressWarnings("all")
public DynamicThreadPoolService dynamicThreadPoolConfigService(HttpAgent httpAgent,
ServerHealthCheck serverHealthCheck,
- ServerNotifyConfigBuilder notifyConfigBuilder,
+ ServerModeNotifyConfigBuilder serverModeNotifyConfigBuilder,
Hippo4jBaseSendMessageService hippo4jBaseSendMessageService,
DynamicThreadPoolSubscribeConfig dynamicThreadPoolSubscribeConfig) {
- return new DynamicThreadPoolConfigService(httpAgent, properties, notifyConfigBuilder, hippo4jBaseSendMessageService, dynamicThreadPoolSubscribeConfig);
+ return new DynamicThreadPoolConfigService(httpAgent, properties, serverModeNotifyConfigBuilder, hippo4jBaseSendMessageService, dynamicThreadPoolSubscribeConfig);
}
@Bean
@@ -205,7 +205,7 @@ public class DynamicThreadPoolAutoConfiguration {
public NotifyConfigBuilder serverNotifyConfigBuilder(HttpAgent httpAgent,
BootstrapProperties properties,
AlarmControlHandler alarmControlHandler) {
- return new ServerNotifyConfigBuilder(httpAgent, properties, alarmControlHandler);
+ return new ServerModeNotifyConfigBuilder(httpAgent, properties, alarmControlHandler);
}
@Bean
diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/notify/ServerNotifyConfigBuilder.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/notify/ServerModeNotifyConfigBuilder.java
similarity index 97%
rename from hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/notify/ServerNotifyConfigBuilder.java
rename to hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/notify/ServerModeNotifyConfigBuilder.java
index 8aeedb98..3cfbe586 100644
--- a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/notify/ServerNotifyConfigBuilder.java
+++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/notify/ServerModeNotifyConfigBuilder.java
@@ -41,11 +41,11 @@ import java.util.Objects;
import static cn.hippo4j.common.constant.Constants.BASE_PATH;
/**
- * Server notify config builder.
+ * Server mode notify config builder.
*/
@Slf4j
@AllArgsConstructor
-public class ServerNotifyConfigBuilder implements NotifyConfigBuilder {
+public class ServerModeNotifyConfigBuilder implements NotifyConfigBuilder {
private final HttpAgent httpAgent;
diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/support/DynamicThreadPoolConfigService.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/support/DynamicThreadPoolConfigService.java
index 663b07dc..f648b346 100644
--- a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/support/DynamicThreadPoolConfigService.java
+++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/support/DynamicThreadPoolConfigService.java
@@ -35,7 +35,7 @@ import cn.hippo4j.message.service.Hippo4jBaseSendMessageService;
import cn.hippo4j.message.service.ThreadPoolNotifyAlarm;
import cn.hippo4j.springboot.starter.config.BootstrapProperties;
import cn.hippo4j.springboot.starter.core.DynamicThreadPoolSubscribeConfig;
-import cn.hippo4j.springboot.starter.notify.ServerNotifyConfigBuilder;
+import cn.hippo4j.springboot.starter.notify.ServerModeNotifyConfigBuilder;
import cn.hippo4j.springboot.starter.remote.HttpAgent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -58,7 +58,7 @@ public class DynamicThreadPoolConfigService extends AbstractDynamicThreadPoolSer
private final BootstrapProperties properties;
- private final ServerNotifyConfigBuilder notifyConfigBuilder;
+ private final ServerModeNotifyConfigBuilder serverModeNotifyConfigBuilder;
private final Hippo4jBaseSendMessageService hippo4jBaseSendMessageService;
@@ -108,7 +108,7 @@ public class DynamicThreadPoolConfigService extends AbstractDynamicThreadPoolSer
registerParameter.getActiveAlarm(),
registerParameter.getCapacityAlarm());
GlobalNotifyAlarmManage.put(registerParameter.getThreadPoolId(), threadPoolNotifyAlarm);
- Map> builderNotify = notifyConfigBuilder.getAndInitNotify(CollectionUtil.newArrayList(registerParameter.getThreadPoolId()));
+ Map> builderNotify = serverModeNotifyConfigBuilder.getAndInitNotify(CollectionUtil.newArrayList(registerParameter.getThreadPoolId()));
hippo4jBaseSendMessageService.putPlatform(builderNotify);
}