From 5e2e3a3be350a9f5baa5ce0e3dd9b651f2dc9eb9 Mon Sep 17 00:00:00 2001 From: Xin Chen <37373516+DDreame@users.noreply.github.com> Date: Sun, 28 May 2023 14:43:58 +0800 Subject: [PATCH 1/4] add UnitTest about MessageConvert (#1358) * add UnitTest about MessageConvert * add UnitTest about MessageConvert * add UnitTest about MessageConvert --- .../common/toolkit/MessageConvert.java | 4 + .../common/toolkit/MessageConvertTest.java | 110 ++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 infra/common/src/test/java/cn/hippo4j/common/toolkit/MessageConvertTest.java diff --git a/infra/common/src/main/java/cn/hippo4j/common/toolkit/MessageConvert.java b/infra/common/src/main/java/cn/hippo4j/common/toolkit/MessageConvert.java index 3be85745..6a5d1fbc 100644 --- a/infra/common/src/main/java/cn/hippo4j/common/toolkit/MessageConvert.java +++ b/infra/common/src/main/java/cn/hippo4j/common/toolkit/MessageConvert.java @@ -31,6 +31,10 @@ import lombok.SneakyThrows; */ public class MessageConvert { + private MessageConvert(){ + + } + /** * {@link Message} to {@link MessageWrapper}. * diff --git a/infra/common/src/test/java/cn/hippo4j/common/toolkit/MessageConvertTest.java b/infra/common/src/test/java/cn/hippo4j/common/toolkit/MessageConvertTest.java new file mode 100644 index 00000000..88677d9f --- /dev/null +++ b/infra/common/src/test/java/cn/hippo4j/common/toolkit/MessageConvertTest.java @@ -0,0 +1,110 @@ +/* + * 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.common.toolkit; + +import cn.hippo4j.common.model.ThreadPoolRunStateInfo; +import cn.hippo4j.common.monitor.*; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; + +/*** + * @description : Todo + * @author : DDDreame + * @date : 2023/5/27 23:24 + */ +public class MessageConvertTest { + + @Test + public void testConvert() { + AbstractMessage message = new RuntimeMessage(); + List runtimeMessages = new ArrayList<>(); + ThreadPoolRunStateInfo poolRunState = ThreadPoolRunStateInfo.builder() + .tpId("testTPid") + .activeSize(4) + .poolSize(12) + .completedTaskCount(8L) + .largestPoolSize(12) + .currentLoad("6") + .clientLastRefreshTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))) + .peakLoad("20") + .queueSize(0) + .queueRemainingCapacity(512) + .rejectCount(0L) + .timestamp(System.currentTimeMillis()) + .build(); + RuntimeMessage runtimeMessage = BeanUtil.convert(poolRunState, RuntimeMessage.class); + runtimeMessage.setGroupKey("test-groupKeys"); + runtimeMessages.add(runtimeMessage); + + message.setMessageType(MessageTypeEnum.RUNTIME); + message.setMessages(runtimeMessages); + MessageWrapper messageWrapper = MessageConvert.convert(message); + Assertions.assertNotNull(messageWrapper); + } + + @Test + public void testMessageWrapperConvert() { + AbstractMessage message = new RuntimeMessage(); + List runtimeMessages = new ArrayList<>(); + ThreadPoolRunStateInfo poolRunState = ThreadPoolRunStateInfo.builder() + .tpId("testTPid") + .activeSize(4) + .poolSize(12) + .completedTaskCount(8L) + .largestPoolSize(12) + .currentLoad("6") + .clientLastRefreshTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))) + .peakLoad("20") + .queueSize(0) + .queueRemainingCapacity(512) + .rejectCount(0L) + .timestamp(System.currentTimeMillis()) + .build(); + RuntimeMessage runtimeMessage = BeanUtil.convert(poolRunState, RuntimeMessage.class); + runtimeMessage.setGroupKey("test-groupKeys"); + runtimeMessages.add(runtimeMessage); + + message.setMessageType(MessageTypeEnum.RUNTIME); + message.setMessages(runtimeMessages); + MessageWrapper messageWrapper = MessageConvert.convert(message); + Message messageResult = MessageConvert.convert(messageWrapper); + Assertions.assertNotNull(messageResult); + Assertions.assertEquals(message, messageResult); + } + + @Test + public void testMessageWrapperConvertException() { + Assertions.assertThrows(Exception.class, ()->{ + Map data1 = new HashMap<>(); + data1.put("key1", "value1"); + data1.put("key2", 123); + Map data2 = new HashMap<>(); + data2.put("key3", true); + data2.put("key4", 3.14); + List> contentParams = Arrays.asList(data1, data2); + Class responseClass = String.class; + MessageTypeEnum messageType = MessageTypeEnum.DEFAULT; + MessageWrapper messageWrapper = new MessageWrapper(contentParams, responseClass, messageType); + MessageConvert.convert(messageWrapper); + }); + } +} From 08cc67c07e6118fcca8cbdb4271c1a740ada2b3b Mon Sep 17 00:00:00 2001 From: furaul Date: Sun, 28 May 2023 14:55:46 +0800 Subject: [PATCH 2/4] prototype version of dubbo threadpool agent. (#1357) * prototype version of dubbo threadpool agent. * rename to optimze & fix ci errors. * rename to optimze & fix ci errors. --- .../adapter-plugins/dubbo-plugin/pom.xml | 29 +++++++ .../adapter/dubbo/DubboThreadPoolAdapter.java | 87 +++++++++++++++++++ .../adapter-plugins/pom.xml | 5 ++ .../spring-boot-1x-plugin/pom.xml | 6 ++ .../EventPublishingFinishedInterceptor.java | 2 + agent/pom.xml | 5 ++ 6 files changed, 134 insertions(+) create mode 100644 agent/hippo4j-agent-plugin/adapter-plugins/dubbo-plugin/pom.xml create mode 100644 agent/hippo4j-agent-plugin/adapter-plugins/dubbo-plugin/src/main/java/cn/hippo4j/agent/adapter/dubbo/DubboThreadPoolAdapter.java diff --git a/agent/hippo4j-agent-plugin/adapter-plugins/dubbo-plugin/pom.xml b/agent/hippo4j-agent-plugin/adapter-plugins/dubbo-plugin/pom.xml new file mode 100644 index 00000000..5304c6eb --- /dev/null +++ b/agent/hippo4j-agent-plugin/adapter-plugins/dubbo-plugin/pom.xml @@ -0,0 +1,29 @@ + + + + hippo4j-agent-adapter-plugins + cn.hippo4j + ${revision} + + 4.0.0 + + dubbo-plugin + + + + org.apache.dubbo + dubbo + provided + + + + cn.hippo4j + hippo4j-threadpool-infra-common + ${project.version} + + + + + \ No newline at end of file diff --git a/agent/hippo4j-agent-plugin/adapter-plugins/dubbo-plugin/src/main/java/cn/hippo4j/agent/adapter/dubbo/DubboThreadPoolAdapter.java b/agent/hippo4j-agent-plugin/adapter-plugins/dubbo-plugin/src/main/java/cn/hippo4j/agent/adapter/dubbo/DubboThreadPoolAdapter.java new file mode 100644 index 00000000..855972ea --- /dev/null +++ b/agent/hippo4j-agent-plugin/adapter-plugins/dubbo-plugin/src/main/java/cn/hippo4j/agent/adapter/dubbo/DubboThreadPoolAdapter.java @@ -0,0 +1,87 @@ +/* + * 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.agent.adapter.dubbo; + +import cn.hippo4j.common.executor.ThreadPoolRegistry; +import cn.hippo4j.common.executor.support.BlockingQueueTypeEnum; +import cn.hippo4j.common.executor.support.RejectedPolicyTypeEnum; +import cn.hippo4j.common.model.executor.ExecutorProperties; +import cn.hippo4j.common.toolkit.BooleanUtil; +import cn.hippo4j.common.toolkit.ReflectUtil; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ThreadPoolExecutor; +import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.store.DataStore; +import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; + +/** + * Dubbo thread-pool adapter. + */ +public class DubboThreadPoolAdapter { + + public static void registerExecutors() { + boolean isLegacyVersion = true; + String poolKey = ExecutorService.class.getName(); + // Since 2.7.5, Dubbo has changed the way thread pools are used + // fixed https://github.com/opengoofy/hippo4j/issues/708 + try { + if (Version.getIntVersion(Version.getVersion()) < 2070500) { + isLegacyVersion = false; + } + } catch (Exception ex) { + } + + try { + if (isLegacyVersion) { + DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension(); + Map executors = dataStore.get(poolKey); + executors.forEach((key, value) -> putHolder(mark() + key, (ThreadPoolExecutor) value)); + return; + } + ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); + ConcurrentMap> data = + (ConcurrentMap>) ReflectUtil.getFieldValue(executorRepository, "data"); + ConcurrentMap executorServiceMap = data.get(poolKey); + executorServiceMap.forEach((key, value) -> putHolder(mark() + key, (ThreadPoolExecutor) value)); + } catch (Exception ex) { + } + } + + private static void putHolder(String executorName, ThreadPoolExecutor executor) { + if (executor == null) { + return; + } + ExecutorProperties executorProperties = ExecutorProperties.builder() + .threadPoolId(executorName) + .corePoolSize(executor.getCorePoolSize()) + .maximumPoolSize(executor.getMaximumPoolSize()) + .allowCoreThreadTimeOut(BooleanUtil.toBoolean(String.valueOf(executor.allowsCoreThreadTimeOut()))) + .blockingQueue(BlockingQueueTypeEnum.getBlockingQueueTypeEnumByName(executor.getQueue().getClass().getSimpleName()).getName()) + .queueCapacity(executor.getQueue().remainingCapacity()) + .rejectedHandler(RejectedPolicyTypeEnum.getRejectedPolicyTypeEnumByName(executor.getRejectedExecutionHandler().getClass().getSimpleName()).getName()) + .build(); + ThreadPoolRegistry.putHolder(executorName, executor, executorProperties); + } + + public static String mark() { + return "Dubbo"; + } +} diff --git a/agent/hippo4j-agent-plugin/adapter-plugins/pom.xml b/agent/hippo4j-agent-plugin/adapter-plugins/pom.xml index 38bfb05c..1c52b2e9 100644 --- a/agent/hippo4j-agent-plugin/adapter-plugins/pom.xml +++ b/agent/hippo4j-agent-plugin/adapter-plugins/pom.xml @@ -10,6 +10,7 @@ hippo4j-agent-adapter-plugins + pom 8 @@ -17,4 +18,8 @@ UTF-8 + + dubbo-plugin + + \ No newline at end of file diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/pom.xml b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/pom.xml index ccec3c7b..b3d2cbf9 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/pom.xml +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/pom.xml @@ -49,6 +49,12 @@ ${project.version} provided + + + cn.hippo4j + dubbo-plugin + + \ No newline at end of file diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/EventPublishingFinishedInterceptor.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/EventPublishingFinishedInterceptor.java index 93b7d1ef..777194f0 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/EventPublishingFinishedInterceptor.java +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/EventPublishingFinishedInterceptor.java @@ -17,6 +17,7 @@ package cn.hippo4j.agent.plugin.spring.boot.v1.interceptor; +import cn.hippo4j.agent.adapter.dubbo.DubboThreadPoolAdapter; import cn.hippo4j.agent.core.logging.api.ILog; import cn.hippo4j.agent.core.logging.api.LogManager; import cn.hippo4j.agent.core.plugin.interceptor.enhance.EnhancedInstance; @@ -56,6 +57,7 @@ public class EventPublishingFinishedInterceptor implements InstanceMethodsAround SpringPropertiesLoader.loadSpringProperties(context.getEnvironment()); ThreadPoolDynamicRefresh dynamicRefreshSpring1x = new DynamicThreadPoolChangeHandlerSpring1x(context); dynamicRefreshSpring1x.registerListener(); + DubboThreadPoolAdapter.registerExecutors(); return ret; } diff --git a/agent/pom.xml b/agent/pom.xml index d0a8b793..0d899eab 100644 --- a/agent/pom.xml +++ b/agent/pom.xml @@ -154,6 +154,11 @@ ${jmh.version} test + + cn.hippo4j + dubbo-plugin + ${project.version} + From 5d40f66e7c94238f79fe231744059db1036dc450 Mon Sep 17 00:00:00 2001 From: magestack Date: Sun, 28 May 2023 16:59:42 +0800 Subject: [PATCH 3/4] Update using company (#1359) --- docs/i18n/zh/docusaurus-plugin-content-pages/users.md | 3 ++- docs/src/pages/users.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/i18n/zh/docusaurus-plugin-content-pages/users.md b/docs/i18n/zh/docusaurus-plugin-content-pages/users.md index c780d5e1..f06de39a 100644 --- a/docs/i18n/zh/docusaurus-plugin-content-pages/users.md +++ b/docs/i18n/zh/docusaurus-plugin-content-pages/users.md @@ -5,7 +5,7 @@ title: 采用公司 ## 谁在使用 Hippo4j -共计 38+ 家公司生产接入 Hippo4j,按照公司登记时间排序。 +共计 39+ 家公司生产接入 Hippo4j,按照公司登记时间排序。 - [身边云](https://serviceshare.com) - [思派健康科技](https://www.medbanks.cn) @@ -45,6 +45,7 @@ title: 采用公司 - [神州数码(西安)](https://www.digitalchina.com) - [广联达科技股份有限公司](https://www.glodon.com) - [天健联创控股集团有限公司](https://www.tjlc.com.cn) +- [知乎](https://www.zhihu.com/) ## 登记 diff --git a/docs/src/pages/users.md b/docs/src/pages/users.md index c780d5e1..f06de39a 100644 --- a/docs/src/pages/users.md +++ b/docs/src/pages/users.md @@ -5,7 +5,7 @@ title: 采用公司 ## 谁在使用 Hippo4j -共计 38+ 家公司生产接入 Hippo4j,按照公司登记时间排序。 +共计 39+ 家公司生产接入 Hippo4j,按照公司登记时间排序。 - [身边云](https://serviceshare.com) - [思派健康科技](https://www.medbanks.cn) @@ -45,6 +45,7 @@ title: 采用公司 - [神州数码(西安)](https://www.digitalchina.com) - [广联达科技股份有限公司](https://www.glodon.com) - [天健联创控股集团有限公司](https://www.tjlc.com.cn) +- [知乎](https://www.zhihu.com/) ## 登记 From 9264919060861b0161f6929ba4c46c090cef501e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=97=B6=E9=97=B4=E9=82=AE=E9=80=92=E5=91=98?= <78356082+barret-yzh@users.noreply.github.com> Date: Tue, 30 May 2023 18:48:06 +0800 Subject: [PATCH 4/4] Add test case for ThreadPoolExecutorUtil (#1356) * Create ThreadFactoryBuilderTest * Update ThreadFactoryBuilderTest Methods are covered by multiple unit test cases . Console printing in English * Update ThreadFactoryBuilderTest Add open source protocol. use @before annotation * Update ThreadFactoryBuilderTest * Update ThreadFactoryBuilderTest * Update ThreadFactoryBuilderTest * Add test case for MessageWrapper * Update MessageWrapperTest * Add test case for ThreadPoolExecutorUtil Add test case for ThreadPoolExecutorUtil * Update ThreadPoolExecutorUtilTest --- .../executor/ThreadPoolExecutorUtilTest | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 infra/common/src/test/java/cn/hippo4j/common/executor/ThreadPoolExecutorUtilTest diff --git a/infra/common/src/test/java/cn/hippo4j/common/executor/ThreadPoolExecutorUtilTest b/infra/common/src/test/java/cn/hippo4j/common/executor/ThreadPoolExecutorUtilTest new file mode 100644 index 00000000..c3459d03 --- /dev/null +++ b/infra/common/src/test/java/cn/hippo4j/common/executor/ThreadPoolExecutorUtilTest @@ -0,0 +1,89 @@ +/* + * 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.common.executor; + +import cn.hippo4j.common.toolkit.ThreadPoolExecutorUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class ThreadPoolExecutorUtilTest { + + private ThreadPoolExecutor executor; + private int corePoolSize; + private int maxPoolSize; + + @Before + public void testSafeSetPoolSize() { + corePoolSize = 2; + maxPoolSize = 4; + executor = new ThreadPoolExecutor( + corePoolSize, + maxPoolSize, + 1L, + TimeUnit.SECONDS, + new ArrayBlockingQueue<>(10) + ); + } + + @Test + public void testEquals(){ + // Test when the new core pool size equals the original maximum pool size. + int newCorePoolSize1 = maxPoolSize; + int newMaxPoolSize1 = 6; + ThreadPoolExecutorUtil.safeSetPoolSize(executor, newCorePoolSize1, newMaxPoolSize1); + Assert.assertEquals(newCorePoolSize1, executor.getCorePoolSize()); + Assert.assertEquals(newMaxPoolSize1, executor.getMaximumPoolSize()); + } + + @Test + public void testGreater(){ + // Test when the new core pool size is greater than the original maximum pool size. + int newCorePoolSize2 = 8; + int newMaxPoolSize2 = 10; + ThreadPoolExecutorUtil.safeSetPoolSize(executor, newCorePoolSize2, newMaxPoolSize2); + Assert.assertEquals(newCorePoolSize2, executor.getCorePoolSize()); + Assert.assertEquals(newMaxPoolSize2, executor.getMaximumPoolSize()); + } + + @Test + public void testLess(){ + // Test when the new core pool size is less than the original maximum pool size. + int newCorePoolSize3 = 3; + int newMaxPoolSize3 = 5; + ThreadPoolExecutorUtil.safeSetPoolSize(executor, newCorePoolSize3, newMaxPoolSize3); + Assert.assertEquals(newCorePoolSize3, executor.getCorePoolSize()); + Assert.assertEquals(newMaxPoolSize3, executor.getMaximumPoolSize()); + } + + @Test + public void testException(){ + // Test when the new core pool size is greater than the new maximum pool size, which should throw an IllegalArgumentException. + int newCorePoolSize4 = 6; + int newMaxPoolSize4 = 4; + try { + ThreadPoolExecutorUtil.safeSetPoolSize(executor, newCorePoolSize4, newMaxPoolSize4); + } catch (IllegalArgumentException e) { + // Expected to throw an exception. + Assert.assertEquals("newCorePoolSize must be smaller than newMaximumPoolSize", e.getMessage()); + } + } +}