add spi test (#957)

* Simplified DynamicThreadPool usage

* Simplified DynamicThreadPool usage

* init

* add test

* format code

* format code

* update doc

* Simplify the code
pull/961/head
weihubeats 2 years ago committed by GitHub
parent 6e2a63f9b6
commit ed0847759d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -26,12 +26,14 @@ import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import cn.hippo4j.common.spi.annotation.SingletonSPI;
/**
* Dynamic thread-pool service loader.
*/
public class DynamicThreadPoolServiceLoader {
private static final Map<Class<?>, Collection<Object>> SERVICES = new ConcurrentHashMap();
private static final Map<Class<?>, Collection<Object>> SERVICES = new ConcurrentHashMap<>();
/**
* Register.
@ -59,6 +61,17 @@ public class DynamicThreadPoolServiceLoader {
return result;
}
/**
* Get Service instances
*
* @param serviceClass serviceClass
* @param <T>
* @return
*/
public static <T> Collection<T> getServiceInstances(final Class<T> serviceClass) {
return null == serviceClass.getAnnotation(SingletonSPI.class) ? newServiceInstances(serviceClass) : getSingletonServiceInstances(serviceClass);
}
/**
* Get singleton service instances.
*
@ -66,6 +79,7 @@ public class DynamicThreadPoolServiceLoader {
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T> Collection<T> getSingletonServiceInstances(final Class<T> service) {
return (Collection<T>) SERVICES.getOrDefault(service, Collections.emptyList());
}

@ -0,0 +1,31 @@
/*
* 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.spi.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation of singleton SPI.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SingletonSPI {
}

@ -17,5 +17,57 @@
package cn.hippo4j.common.spi;
import java.util.Collection;
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertTrue;
/**
* test {@link DynamicThreadPoolServiceLoader}
*/
public final class DynamicThreadPoolServiceLoaderTest {
@Test
public void assertRegister() {
DynamicThreadPoolServiceLoader.register(Collection.class);
Collection<?> collections = DynamicThreadPoolServiceLoader.getSingletonServiceInstances(Collection.class);
assertTrue(collections.isEmpty());
}
@Test
public void assertGetSingletonServiceInstances() {
DynamicThreadPoolServiceLoader.register(TestSingletonInterfaceSPI.class);
Collection<TestSingletonInterfaceSPI> instances = DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestSingletonInterfaceSPI.class);
assertThat(instances.size(), equalTo(1));
assertThat(instances.iterator().next(), is(DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestSingletonInterfaceSPI.class).iterator().next()));
}
@Test
public void assertNewServiceInstances() {
DynamicThreadPoolServiceLoader.register(TestSingletonInterfaceSPI.class);
Collection<TestSingletonInterfaceSPI> instances = DynamicThreadPoolServiceLoader.newServiceInstances(TestSingletonInterfaceSPI.class);
assertThat(instances.size(), equalTo(1));
assertThat(instances.iterator().next(), not(DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestSingletonInterfaceSPI.class).iterator().next()));
}
@Test
public void assertGetServiceInstancesWhenIsSingleton() {
DynamicThreadPoolServiceLoader.register(TestSingletonInterfaceSPI.class);
Collection<TestSingletonInterfaceSPI> instances = DynamicThreadPoolServiceLoader.getServiceInstances(TestSingletonInterfaceSPI.class);
assertThat(instances.iterator().next(), is(DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestSingletonInterfaceSPI.class).iterator().next()));
}
@Test
public void assertGetServiceInstancesWhenNotSingleton() {
DynamicThreadPoolServiceLoader.register(TestInterfaceSPI.class);
Collection<TestInterfaceSPI> instances = DynamicThreadPoolServiceLoader.getServiceInstances(TestInterfaceSPI.class);
assertThat(instances.iterator().next(), not(DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestInterfaceSPI.class).iterator().next()));
}
}

@ -0,0 +1,24 @@
/*
* 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.spi;
/**
* test {@link DynamicThreadPoolServiceLoader}
*/
public interface TestInterfaceSPI {
}

@ -0,0 +1,24 @@
/*
* 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.spi;
/**
* test {@link DynamicThreadPoolServiceLoader}
*/
public class TestInterfaceSPIImpl implements TestInterfaceSPI {
}

@ -0,0 +1,27 @@
/*
* 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.spi;
import cn.hippo4j.common.spi.annotation.SingletonSPI;
/**
* test {@link DynamicThreadPoolServiceLoader}
*/
@SingletonSPI
public interface TestSingletonInterfaceSPI {
}

@ -0,0 +1,24 @@
/*
* 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.spi;
/**
* test {@link DynamicThreadPoolServiceLoader}
*/
public class TestSingletonInterfaceSPIImpl implements TestSingletonInterfaceSPI {
}

@ -0,0 +1,18 @@
#
# 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.
#
cn.hippo4j.common.spi.TestInterfaceSPIImpl

@ -0,0 +1,18 @@
#
# 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.
#
cn.hippo4j.common.spi.TestSingletonInterfaceSPIImpl

@ -147,6 +147,7 @@ public class DynamicThreadPoolElasticSearchMonitorHandler extends AbstractDynami
@Getter
@Builder
private static class EsIndex {
String index;
String type;
String mapping;

@ -17,29 +17,30 @@
package cn.hippo4j.config.springboot.starter.monitor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.design.builder.ThreadFactoryBuilder;
import cn.hippo4j.common.spi.DynamicThreadPoolServiceLoader;
import cn.hippo4j.common.toolkit.StringUtil;
import cn.hippo4j.config.springboot.starter.config.BootstrapConfigProperties;
import cn.hippo4j.config.springboot.starter.config.MonitorProperties;
import cn.hippo4j.core.executor.manage.GlobalThreadPoolManage;
import cn.hippo4j.common.design.builder.ThreadFactoryBuilder;
import cn.hippo4j.monitor.base.DynamicThreadPoolMonitor;
import cn.hippo4j.monitor.base.ThreadPoolMonitor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import static cn.hippo4j.core.executor.manage.GlobalThreadPoolManage.getThreadPoolNum;
/**
@ -67,7 +68,7 @@ public class ThreadPoolMonitorExecutor implements ApplicationRunner, DisposableB
log.info("Start monitoring the running status of dynamic thread pool.");
threadPoolMonitors = new ArrayList<>();
collectScheduledExecutor = new ScheduledThreadPoolExecutor(
new Integer(1),
1,
ThreadFactoryBuilder.builder().daemon(true).prefix("client.scheduled.collect.data").build());
// Get dynamic thread pool monitoring component.
List<String> collectTypes = Arrays.asList(monitor.getCollectTypes().split(","));
@ -77,7 +78,7 @@ public class ThreadPoolMonitorExecutor implements ApplicationRunner, DisposableB
dynamicThreadPoolMonitors.stream().filter(each -> collectTypes.contains(each.getType())).forEach(each -> threadPoolMonitors.add(each));
// Execute dynamic thread pool monitoring component.
collectScheduledExecutor.scheduleWithFixedDelay(
() -> scheduleRunnable(),
this::scheduleRunnable,
properties.getInitialDelay(),
properties.getCollectInterval(),
TimeUnit.MILLISECONDS);
@ -98,6 +99,6 @@ public class ThreadPoolMonitorExecutor implements ApplicationRunner, DisposableB
@Override
public void destroy() throws Exception {
Optional.ofNullable(collectScheduledExecutor).ifPresent(each -> each.shutdown());
Optional.ofNullable(collectScheduledExecutor).ifPresent(ScheduledThreadPoolExecutor::shutdown);
}
}

Loading…
Cancel
Save