From 3ed35efee1350377ccc8b622353aba298ba36de1 Mon Sep 17 00:00:00 2001 From: shiming-stars-lk <1031900093@qq.com> Date: Fri, 15 Jul 2022 10:45:18 +0800 Subject: [PATCH] Add monitoring of Hystrix thread pools --- .../hippo4j-adapter-hystrix/pom.xml | 55 ++++++++ .../hystrix/HystrixThreadPoolAdapter.java | 118 ++++++++++++++++++ hippo4j-adapter/pom.xml | 1 + .../pom.xml | 6 + .../pom.xml | 50 ++++++++ .../HystrixAdapterAutoConfiguration.java | 28 +++++ .../main/resources/META-INF/spring.factories | 1 + .../pom.xml | 1 + pom.xml | 7 ++ 9 files changed, 267 insertions(+) create mode 100644 hippo4j-adapter/hippo4j-adapter-hystrix/pom.xml create mode 100644 hippo4j-adapter/hippo4j-adapter-hystrix/src/main/java/cn/hippo4j/adapter/hystrix/HystrixThreadPoolAdapter.java create mode 100644 hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-hystrix/pom.xml create mode 100644 hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-hystrix/src/main/java/cn/hippo4j/springboot/starter/adapter/hystrix/HystrixAdapterAutoConfiguration.java create mode 100644 hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-hystrix/src/main/resources/META-INF/spring.factories diff --git a/hippo4j-adapter/hippo4j-adapter-hystrix/pom.xml b/hippo4j-adapter/hippo4j-adapter-hystrix/pom.xml new file mode 100644 index 00000000..83e1dba1 --- /dev/null +++ b/hippo4j-adapter/hippo4j-adapter-hystrix/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + cn.hippo4j + hippo4j-adapter + ${revision} + + hippo4j-adapter-hystrix + + + + cn.hippo4j + hippo4j-adapter-base + + + org.springframework.cloud + spring-cloud-starter-netflix-hystrix + ${spring-cloud-starter-netflix-hystrix.version} + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + ${project.artifactId} + ${project.version} + ${maven.build.timestamp} + chen.ma + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.3 + + + + jar + + + + + + + diff --git a/hippo4j-adapter/hippo4j-adapter-hystrix/src/main/java/cn/hippo4j/adapter/hystrix/HystrixThreadPoolAdapter.java b/hippo4j-adapter/hippo4j-adapter-hystrix/src/main/java/cn/hippo4j/adapter/hystrix/HystrixThreadPoolAdapter.java new file mode 100644 index 00000000..1fc1e336 --- /dev/null +++ b/hippo4j-adapter/hippo4j-adapter-hystrix/src/main/java/cn/hippo4j/adapter/hystrix/HystrixThreadPoolAdapter.java @@ -0,0 +1,118 @@ +/* + * 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.adapter.hystrix; + +import cn.hippo4j.adapter.base.ThreadPoolAdapter; +import cn.hippo4j.adapter.base.ThreadPoolAdapterParameter; +import cn.hippo4j.adapter.base.ThreadPoolAdapterState; +import cn.hippo4j.common.toolkit.CollectionUtil; +import com.google.common.collect.Maps; +import com.netflix.hystrix.HystrixThreadPool; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.event.ApplicationStartedEvent; +import org.springframework.context.ApplicationListener; + +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ThreadPoolExecutor; + +import static cn.hippo4j.common.constant.ChangeThreadPoolConstants.CHANGE_DELIMITER; + +/** + * hystrix thread-pool adapter. + */ +@Slf4j +public class HystrixThreadPoolAdapter implements ThreadPoolAdapter, ApplicationListener { + + private static final String THREAD_POOL_FIELD = "threadPool"; + + private static final String THREAD_POOLS_FIELD = "threadPools"; + + private final Map HYSTRIX_CONSUME_EXECUTOR = Maps.newHashMap(); + + @Override + public String mark() { + return "hystrix"; + } + + @Override + public ThreadPoolAdapterState getThreadPoolState(String identify) { + ThreadPoolAdapterState result = new ThreadPoolAdapterState(); + ThreadPoolExecutor rocketMQConsumeExecutor = HYSTRIX_CONSUME_EXECUTOR.get(identify); + if (rocketMQConsumeExecutor != null) { + result.setThreadPoolKey(identify); + result.setCoreSize(rocketMQConsumeExecutor.getCorePoolSize()); + result.setMaximumSize(rocketMQConsumeExecutor.getMaximumPoolSize()); + return result; + } + log.warn("[{}] hystrix thread pool not found.", identify); + return result; + } + + @Override + public boolean updateThreadPool(ThreadPoolAdapterParameter threadPoolAdapterParameter) { + String threadPoolKey = threadPoolAdapterParameter.getThreadPoolKey(); + ThreadPoolExecutor threadPoolExecutor = HYSTRIX_CONSUME_EXECUTOR.get(threadPoolKey); + if (threadPoolExecutor == null) { + log.warn("[{}] hystrix thread pool not found.", threadPoolKey); + return false; + } + int originalCoreSize = threadPoolExecutor.getCorePoolSize(); + int originalMaximumPoolSize = threadPoolExecutor.getMaximumPoolSize(); + threadPoolExecutor.setCorePoolSize(threadPoolAdapterParameter.getCorePoolSize()); + threadPoolExecutor.setMaximumPoolSize(threadPoolAdapterParameter.getMaximumPoolSize()); + log.info("[{}] hystrix thread pool parameter change. coreSize :: {}, maximumSize :: {}", + threadPoolKey, + String.format(CHANGE_DELIMITER, originalCoreSize, threadPoolExecutor.getCorePoolSize()), + String.format(CHANGE_DELIMITER, originalMaximumPoolSize, threadPoolExecutor.getMaximumPoolSize())); + return true; + } + + @Override + public void onApplicationEvent(ApplicationStartedEvent event) { + try { + Class factoryClass = HystrixThreadPool.Factory.class; + Field threadPoolsField = factoryClass.getDeclaredField(THREAD_POOLS_FIELD); + threadPoolsField.setAccessible(true); + ConcurrentHashMap threadPools = + (ConcurrentHashMap)threadPoolsField.get(factoryClass); + if (CollectionUtil.isNotEmpty(threadPools)) { + for (Map.Entry stringHystrixThreadPoolEntry : threadPools.entrySet()) { + String key = stringHystrixThreadPoolEntry.getKey(); + HystrixThreadPool value = stringHystrixThreadPoolEntry.getValue(); + if (value instanceof HystrixThreadPool.HystrixThreadPoolDefault) { + HystrixThreadPool.HystrixThreadPoolDefault hystrixThreadPoolDefault = + (HystrixThreadPool.HystrixThreadPoolDefault)value; + Class hystrixThreadPoolDefaultClass = hystrixThreadPoolDefault.getClass(); + Field threadPoolField = hystrixThreadPoolDefaultClass.getDeclaredField(THREAD_POOL_FIELD); + threadPoolField.setAccessible(true); + ThreadPoolExecutor threadPoolExecutor = + (ThreadPoolExecutor)threadPoolField.get(hystrixThreadPoolDefault); + if (threadPoolExecutor != null) { + HYSTRIX_CONSUME_EXECUTOR.put(key,threadPoolExecutor); + } + } + } + } + }catch (Exception e) { + log.error("Failed to get Hystrix thread pool.", e); + } + } +} diff --git a/hippo4j-adapter/pom.xml b/hippo4j-adapter/pom.xml index 6eef9cd9..2d03f504 100644 --- a/hippo4j-adapter/pom.xml +++ b/hippo4j-adapter/pom.xml @@ -16,6 +16,7 @@ hippo4j-adapter-kafka hippo4j-adapter-rabbitmq hippo4j-adapter-rocketmq + hippo4j-adapter-hystrix hippo4j-adapter-spring-cloud-stream-rocketmq hippo4j-adapter-spring-cloud-stream-kafka diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-all/pom.xml b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-all/pom.xml index 926a59e3..012fb69b 100644 --- a/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-all/pom.xml +++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-all/pom.xml @@ -33,6 +33,12 @@ hippo4j-spring-boot-starter-adapter-dubbo ${revision} + + + cn.hippo4j + hippo4j-spring-boot-starter-adapter-hystrix + ${revision} + diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-hystrix/pom.xml b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-hystrix/pom.xml new file mode 100644 index 00000000..cf5db2f1 --- /dev/null +++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-hystrix/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + cn.hippo4j + hippo4j-spring-boot-starter-adapter + ${revision} + + hippo4j-spring-boot-starter-adapter-hystrix + + + + cn.hippo4j + hippo4j-adapter-hystrix + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + ${project.artifactId} + ${project.version} + ${maven.build.timestamp} + chen.ma + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.3 + + + + jar + + + + + + + diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-hystrix/src/main/java/cn/hippo4j/springboot/starter/adapter/hystrix/HystrixAdapterAutoConfiguration.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-hystrix/src/main/java/cn/hippo4j/springboot/starter/adapter/hystrix/HystrixAdapterAutoConfiguration.java new file mode 100644 index 00000000..9e2d1ac2 --- /dev/null +++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-hystrix/src/main/java/cn/hippo4j/springboot/starter/adapter/hystrix/HystrixAdapterAutoConfiguration.java @@ -0,0 +1,28 @@ +package cn.hippo4j.springboot.starter.adapter.hystrix; + +import cn.hippo4j.adapter.hystrix.HystrixThreadPoolAdapter; +import cn.hippo4j.common.config.ApplicationContextHolder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @program: hippo4j + * @description: + * @author: lk + * @create: 2022-07-15 + **/ +@Configuration(proxyBeanMethods = false) +public class HystrixAdapterAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public ApplicationContextHolder simpleApplicationContextHolder() { + return new ApplicationContextHolder(); + } + + @Bean + public HystrixThreadPoolAdapter hystrixThreadPoolAdapter(){ + return new HystrixThreadPoolAdapter(); + } +} diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-hystrix/src/main/resources/META-INF/spring.factories b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-hystrix/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..e00410f3 --- /dev/null +++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-hystrix/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.hippo4j.springboot.starter.adapter.hystrix.HystrixAdapterAutoConfiguration \ No newline at end of file diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/pom.xml b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/pom.xml index 7caf36aa..647602f7 100644 --- a/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/pom.xml +++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/pom.xml @@ -18,6 +18,7 @@ hippo4j-spring-boot-starter-adapter-kafka hippo4j-spring-boot-starter-adapter-rabbitmq hippo4j-spring-boot-starter-adapter-rocketmq + hippo4j-spring-boot-starter-adapter-hystrix hippo4j-spring-boot-starter-adapter-spring-cloud-stream-kafka hippo4j-spring-boot-starter-adapter-spring-cloud-stream-rocketmq diff --git a/pom.xml b/pom.xml index ad28f873..2cca8e09 100644 --- a/pom.xml +++ b/pom.xml @@ -51,6 +51,7 @@ 9.0.55 2.2.6.RELEASE 4.1.10.Final + 2.2.9.RELEASE false UTF-8 @@ -172,6 +173,12 @@ ${revision} + + cn.hippo4j + hippo4j-adapter-hystrix + ${revision} + + cn.hippo4j hippo4j-adapter-spring-cloud-stream-kafka