spring 集成common-pool2
Common-pool2The Apache Commons Pool open source software library provides an object-pooling API and a number of object pool implementations. Version 2 of Apache Commons Pool contains a completely re-w
Common-pool2
The Apache Commons Pool open source software library provides an object-pooling API and a number of object pool implementations. Version 2 of Apache Commons Pool contains a completely re-written pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance tracking and pool monitoring.
common-pool2 是一个开源的对象池
在高并发情况下避免了重 对象新建的操作。
典型如 httpclient
phantomjs
spring 引入第三方jar 包
spring context 注册第三方jar 包中的对象 一般使用
@Configuration 和@Bean 注解组合
/**
* @author hamish-wu
*/
@Configuration
public class CommonPoolConfig {
@Bean
public static GenericObjectPoolConfig genericObjectPoolConfig() {
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
/* genericObjectPoolConfig.setJmxEnabled(false);*/
return genericObjectPoolConfig;
}
@Bean(name = "mypool")
public GenericObjectPool<HttpClient> getHttpClientPool() {
return new GenericObjectPool<>(pooledHttpClientFactory, genericObjectPoolConfig);
}
}
使用@Bean 注解修饰的方法可以使用 static 修饰,影响spring context 注册顺序
static 修饰的方法会被优先注册
@Bean注解可以自定义bean name
使用的时候 建议搭配 @Resource 注解
另外@bean 注册 可以使用@Import 注解替换,但是@import 注解
不如@bean 注解灵活
spring 集成 common-pool2
2.1 启动类:
@SpringBootApplication(scanBasePackages = {"com.fancv.*", "com.google.common.*"}, exclude = {DataSourceAutoConfiguration.class})
@ServletComponentScan(basePackages = {"com.fancv.filter", "com.fancv.listener"})
@EnableSwagger2
@MapperScan("com.fancv.dao")
@Import({MyConfig.class, GuavaConfig.class, IntMath.class, PooledHttpClientFactory.class})
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class SpringBootApp {
public static void main(String[] args) {
SpringApplication.run(SpringBootApp.class, args);
}
}
2.2 配置类
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.http.client.HttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
/**
* @author hamish-wu
*/
@Configuration
public class CommonPoolConfig {
/**
* Pool 一般配置信息
*/
@Resource
GenericObjectPoolConfig genericObjectPoolConfig;
/**
*
*/
@Resource
PooledHttpClientFactory pooledHttpClientFactory;
@Bean
public static GenericObjectPoolConfig genericObjectPoolConfig() {
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
/* genericObjectPoolConfig.setJmxEnabled(false);*/
return genericObjectPoolConfig;
}
@Bean(name = "mypool")
public GenericObjectPool<HttpClient> getHttpClientPool() {
return new GenericObjectPool<>(pooledHttpClientFactory, genericObjectPoolConfig);
}
}
PooledObjectFactory实现类
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
public class PooledHttpClientFactory implements PooledObjectFactory<HttpClient> {
@Override
public PooledObject<HttpClient> makeObject() throws Exception {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
return new DefaultPooledObject<>(httpClient);
}
@Override
public void destroyObject(PooledObject<HttpClient> pooledObject) throws Exception {
//不处理
}
@Override
public boolean validateObject(PooledObject<HttpClient> pooledObject) {
return true;
}
@Override
public void activateObject(PooledObject<HttpClient> pooledObject) throws Exception {
//不处理
}
@Override
public void passivateObject(PooledObject<HttpClient> pooledObject) throws Exception {
//不处理
}
}
service 层使用
import com.google.common.math.IntMath;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.protocol.HttpClientContext;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* guava 单节点限流
*/
@Service
@Slf4j
public class AccessLimitService {
@Resource(name = "myRate")
RateLimiter hello;
@Resource
IntMath intMath;
@Resource(name = "mypool")
GenericObjectPool<HttpClient> httpClientPool;
/**
* 尝试获取令牌
*/
public Boolean tryAcquire() {
IntMath.isPowerOfTwo(2);
return hello.tryAcquire();
}
/***
* 获取HTTPClient
*/
public String getPage() {
try {
HttpClient client = httpClientPool.borrowObject();
try {
RequestBuilder requestBuilder = RequestBuilder.get("https://www.oschina.net");
requestBuilder.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36");
HttpUriRequest httpUriRequest = requestBuilder.build();
HttpClientContext httpClientContext = new HttpClientContext();
HttpResponse httpResponse = client.execute(httpUriRequest, httpClientContext);
byte[] contentBytes = IOUtils.toByteArray(httpResponse.getEntity().getContent());
System.out.println("获取的网页源码:" + new String(contentBytes, "utf-8"));
log.info("getFactoryType:{}", httpClientPool.getFactoryType());
httpClientPool.returnObject(client);
} catch (Exception ex) {
httpClientPool.invalidateObject(client);
ex.printStackTrace();
}
} catch (final Exception e) {
log.error("获取HttpClient 报错", e);
}
return "hello";
}
}
遇到问题
报错信息
org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [GenericObjectPool [maxTotal=8, blockWhenExhausted=true, maxWaitMillis=-1, lifo=true, fairness=false, testOnCreate=false, testOnBorrow=false, testOnReturn=false, testWhileIdle=false, timeBetweenEvictionRunsMillis=-1, numTestsPerEvictionRun=3, minEvictableIdleTimeMillis=1800000, softMinEvictableIdleTimeMillis=-1, evictionPolicy=org.apache.commons.pool2.impl.DefaultEvictionPolicy@4a03c4bc, closeLock=java.lang.Object@3d0c88f4, closed=false, evictionLock=java.lang.Object@5aad4194, evictor=null, evictionIterator=null, factoryClassLoader=java.lang.ref.WeakReference@50a1c2f3, oname=org.apache.commons.pool2:type=GenericObjectPool,name=pool, creationStackTrace=java.lang.Exception
at org.apache.commons.pool2.impl.BaseGenericObjectPool.<init>(BaseGenericObjectPool.java:147)
at org.apache.commons.pool2.impl.GenericObjectPool.<init>(GenericObjectPool.java:111)
at com.fancv.config.CommonPoolConfig.getHttpClientPool(CommonPoolConfig.java:38)
at com.fancv.config.CommonPoolConfig$$EnhancerBySpringCGLIB$$9d954d11.CGLIB$getHttpClientPool$0(<generated>)
at com.fancv.config.CommonPoolConfig$$EnhancerBySpringCGLIB$$9d954d11$$FastClassBySpringCGLIB$$f8408bf0.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
at com.fancv.config.CommonPoolConfig$$EnhancerBySpringCGLIB$$9d954d11.getHttpClientPool(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:484)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:454)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:543)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:513)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:653)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:224)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:116)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:454)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:543)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:513)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:653)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:224)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:116)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
at com.fancv.SpringBootApp.main(SpringBootApp.java:25)
, borrowedCount=0, returnedCount=0, createdCount=0, destroyedCount=0, destroyedByEvictorCount=0, destroyedByBorrowValidationCount=0, activeTimes=StatsStore [values=[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], size=100, index=0], idleTimes=StatsStore [values=[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], size=100, index=0], waitTimes=StatsStore [values=[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], size=100, index=0], maxBorrowWaitTimeMillis=0, swallowedExceptionListener=null, factoryType=null, maxIdle=8, minIdle=0, factory=com.fancv.config.PooledHttpClientFactory@453ca7f, allObjects={}, createCount=0, idleObjects=[], abandonedConfig=null]] with key 'mypool'; nested exception is javax.management.InstanceAlreadyExistsException: MXBean already registered with name org.apache.commons.pool2:type=GenericObjectPool,name=pool
at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:626) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.jmx.export.MBeanExporter.lambda$registerBeans$2(MBeanExporter.java:552) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at java.base/java.util.HashMap.forEach(HashMap.java:1336) ~[na:na]
at org.springframework.jmx.export.MBeanExporter.registerBeans(MBeanExporter.java:552) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.jmx.export.MBeanExporter.afterSingletonsInstantiated(MBeanExporter.java:435) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:896) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at com.fancv.SpringBootApp.main(SpringBootApp.java:25) ~[classes/:na]
Caused by: javax.management.InstanceAlreadyExistsException: MXBean already registered with name org.apache.commons.pool2:type=GenericObjectPool,name=pool
at java.management/com.sun.jmx.mbeanserver.MXBeanLookup.addReference(MXBeanLookup.java:151) ~[na:na]
at java.management/com.sun.jmx.mbeanserver.MXBeanSupport.register(MXBeanSupport.java:160) ~[na:na]
at java.management/com.sun.jmx.mbeanserver.MBeanSupport.preRegister2(MBeanSupport.java:173) ~[na:na]
at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(DefaultMBeanServerInterceptor.java:919) ~[na:na]
at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:890) ~[na:na]
at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:320) ~[na:na]
at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522) ~[na:na]
at org.springframework.jmx.support.MBeanRegistrationSupport.doRegister(MBeanRegistrationSupport.java:138) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.jmx.export.MBeanExporter.registerBeanInstance(MBeanExporter.java:672) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:616) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
... 14 common frames omitted
原因分析:
MXBean already registered,bean已经被注册
GenericObjectPoolConfig被注册的时候 自动注册了一个GenericObjectPool
解决方法:
1.启动类加上:
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
2.bean GenericObjectPoolConfig中有一个genericObjectPoolConfig.setJmxEnabled(false); 关掉监控 这个异常就不会抛出了~
思考
1.spring 中注册第三方jar包的对象
2.@bean 和@import的异同
3.common-pool 中Pool 的初始化
4.spring 注册 bean的顺序
参考资料:https://www.cnblogs.com/gaoquanquan/p/11347843.html
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)