Apache对象池commons.pool使用

背景:

要抓取网络数据,使用了chromedriver。因为创建和销毁驱动耗时间,所以考虑使用对象池管理。刚好apache提供了开源库,不用重复造轮子了。并且支持多key的池子。如:手机端的驱动放一个池子中,PC端的驱动放一个池子中。简单使用如下:

maven引入:

<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-pool2</artifactId>
	<version>2.4.2</version>
</dependency>
模式类型枚举
public enum EnumDriverObject {
	chrome_pc("PC模式"),
	chrome_phone("Phone模式");
	EnumDriverObject(String text){
	}
}
对象池工厂
import org.apache.commons.pool2.KeyedPooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;

import java.util.HashMap;
import java.util.Map;

/**
 * @desc:apache对象池,基于key的多模式对象池
 * @author: hecj
 **/
public class DriverObjectKeyFactory implements KeyedPooledObjectFactory<String, Object> {
	private final static Logger log = LoggerFactory.getLogger(DriverObjectKeyFactory.class);
	
	private static GenericKeyedObjectPool genericKeyedObjectPool = null;
	
	private static Object lock = new Object();
	
	// 最大驱动个数
	private static int maxDriverCount = 20;
	// 初始化驱动个数
	private static int initDriverCount = 2;
	
	// 空闲驱动个数
	private static int idleDriverCount = 2;
	// 最大个数
	private static int maxTotal = 100;
	private static Long maxWait = 10000l;
	/**
	* 单例
	*/
	public static GenericKeyedObjectPool getInstance() {
		if (genericKeyedObjectPool == null) {
			synchronized (lock) {
				if (genericKeyedObjectPool == null) {
					try{
						Environment env = SpringUtil.getBean(Environment.class);
						maxDriverCount = Integer.parseInt(env.getProperty("chrome.maxDriverCount"));
						idleDriverCount = Integer.parseInt(env.getProperty("chrome.idleDriverCount"));
						initDriverCount = Integer.parseInt(env.getProperty("xylink.chrome.initDriverCount"));
						maxTotal = Integer.parseInt(env.getProperty("chrome.maxTotal"));
						maxWait = Long.parseLong(env.getProperty("chrome.maxWait"));
					} catch (Exception ex){
					}
					GenericKeyedObjectPoolConfig genericKeyedObjectPoolConfig = new GenericKeyedObjectPoolConfig();
					genericKeyedObjectPoolConfig.setMaxIdlePerKey(idleDriverCount);
					genericKeyedObjectPoolConfig.setMaxTotalPerKey(maxDriverCount);
					genericKeyedObjectPoolConfig.setMaxTotal(maxTotal);
					genericKeyedObjectPoolConfig.setMinIdlePerKey(initDriverCount);
					genericKeyedObjectPoolConfig.setMaxWaitMillis(maxWait);
					DriverObjectKeyFactory driverObjectKeyFactory = new DriverObjectKeyFactory();
					genericKeyedObjectPool = new GenericKeyedObjectPool<>(driverObjectKeyFactory, genericKeyedObjectPoolConfig);
				}
			}
		}
		return genericKeyedObjectPool;
	}
	/**
	* 根据key创建对应的对象
	*/
	@Override
	public PooledObject<Object> makeObject(String key) throws Exception {
		Object object = null;
		if(EnumDriverObject.chrome_pc.name().equals(key)){
			ChromeOptions chromeOptions = new ChromeOptions();
			chromeOptions.addArguments("--headless");
			object = new ChromeDriver(chromeOptions);
		} else if(EnumDriverObject.chrome_phone.name().equals(key)) {
			ChromeOptions chromeOptions = new ChromeOptions();
			chromeOptions.addArguments("--headless");
			Map<String, Object> deviceMetrics = new HashMap<String, Object>();
			deviceMetrics.put("width", 360);
			deviceMetrics.put("height", 640);
			deviceMetrics.put("pixelRatio", 3.0);
			Map<String, Object> mobileEmulation = new HashMap<String, Object>();
			mobileEmulation.put("deviceMetrics", deviceMetrics);
			mobileEmulation.put("userAgent", "Mozilla/5.0 (Linux; Android 8.1.0; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19");
			chromeOptions.setExperimentalOption("mobileEmulation", mobileEmulation);
			object = new ChromeDriver(chromeOptions);
		}else{
			log.error("对象key无效");
			throw new RuntimeException("对象key无效");
		}
		return new DefaultPooledObject<>(object);
	}
	
	/**
	* 对象销毁时执行 对应方法:genericKeyedObjectPool.invalidateObject
	*/
	@Override
	public void destroyObject(String key, PooledObject<Object> p) throws Exception {
		Object object = p.getObject();
		if(object instanceof ChromeDriver){
			((ChromeDriver)object).quit();
		}
	}
	
	@Override
	public boolean validateObject(String key, PooledObject<Object> p) {
		return p.getObject() != null;
	}
	
	@Override
	public void activateObject(String key, PooledObject<Object> p) throws Exception {
	}
	
	@Override
	public void passivateObject(String key, PooledObject<Object> p) throws Exception {
	
	}
}
调用方式
GenericKeyedObjectPool genericKeyedObjectPool = DriverObjectKeyFactory.getInstance();
// 先从池子中拿一个对象
ChromeDriver driver = (ChromeDriver)genericKeyedObjectPool.borrowObject(EnumDriverObject.chrome_pc);
...
doSomething();
...
// 用完之后释放掉
genericKeyedObjectPool.returnObject(EnumDriverObject.chrome_pc,driver);
// 如果对象有问题,也可以销毁掉
genericKeyedObjectPool.invalidateObject(EnumDriverObject.chrome_pc,driver);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值