近日接手一个项目功能的性能优化,该功能主要实现selenium截图。在测试的过程中就发现其创建selenium.WebDriver耗时特别长,于是就想着通过将其对象池化,减少不必要的对象创建/销毁,但是手写管理池比较麻烦,最终采用Apache Commons Pool的GenericObjectPool来实现。
什么是GenericObjectPool?
GenericObjectPool类是Apache Commons Pool库的一部分,用于提供一个通用、高度可配置的对象池实现。它可以很好的控制对象池中对象的数量,一个新的请求如果对象池空,GenericObjectPool会自动的创建新对象。
其核心流程如下:
image.png
创建GenericObjectPool
创建GenericObjectPool的第一步是创建一个BasePooledObjectFactory,这样GenericObjectPool才知道怎么样创建新的对象,理论上,任何对象都可以被池化。
public static class WebDriverFactory extends BasePooledObjectFactory<WebDriver> {
@Override
public WebDriver create() {
// 创建对象
ChromeOptions options = new ChromeOptions();
return new ChromeDriver(options);
}
@Override
public PooledObject<WebDriver> wrap(WebDriver obj) {
return new DefaultPooledObject<>(obj);
}
@Override
public boolean validateObject(PooledObject<WebDriver> p) {
// 当需要时在这里实现WebDriver实例的有效性验证
try {
p.getObject().getCurrentUrl(); // 尝试获取当前URL
return true; // 没有抛出异常,实例有效
} catch (Exception e) {
return false; // 抛出异常,实例无效
}
}
@Override
public void destroyObject(PooledObject<WebDriver> p) {
// 销毁对象
p.getObject().quit();
}
}
然后,只需要通过这个对象工厂来创建GenericObjectPool:
// 创建Apache Commons Pool2配置
GenericObjectPoolConfig<WebDriver> poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setMinIdle(minIdle);
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMaxTotal(maxTotal);
poolConfig.setTestOnBorrow(true);
//poolConfig.setMaxWait(Duration.of(10, ChronoUnit.SECONDS));
// 创建一个WebDriver工厂,以提供给GenericObjectPool
WebDriverFactory factory = new WebDriverFactory();
// 根据我们的配置和工厂创建内部pool
GenericObjectPool<WebDriver> myPool = new GenericObjectPool<>(factory, poolConfig);
它会创建一个新的GenericObjectPool实例,然后使用你的WebDriverFactory实例生成新的对象。
使用GenericObjectPool
一旦有了GenericObjectPool的实例,就可以使用borrowObject方法来获取对象。
WebDriver myObject = null;
try {
myObject = myPool.borrowObject();
// 对象使用
} finally {
myPool.returnObject(myObject); // 不再需要时,返回对象到池中
}
网友评论