package com.virjar.dungproxy.client.samples.poolstrategy; import java.io.StringReader; import java.util.Iterator; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; import org.apache.commons.io.LineIterator; import org.apache.commons.lang3.math.NumberUtils; import org.apache.http.client.protocol.HttpClientContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Splitter; import com.google.common.collect.Lists; import com.google.common.util.concurrent.RateLimiter; import com.virjar.dungproxy.client.httpclient.HttpInvoker; import com.virjar.dungproxy.client.ippool.strategy.ResourceFacade; import com.virjar.dungproxy.client.model.AvProxyVO; import com.virjar.dungproxy.client.util.CommonUtil; import com.virjar.dungproxy.client.util.PoolUtil; /** * Created by virjar on 17/2/14.<br/> * 无忧代理接入demo data5u.com */ public class U5IpSource implements ResourceFacade { private static final Logger logger = LoggerFactory.getLogger(U5IpSource.class); /** * 无忧代理每次只能返回几个IP,但是短时间可以多次获取IP */ private ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy()); private List<AvProxyVO> cache = Lists.newLinkedList();// 链表效率高 private ReentrantLock lock = new ReentrantLock(); // 无忧代理每秒不能超过5此,所以添加限流器,我们发现无忧代理的实现不是这个规则,没有超过5此也会被封,测试发现每秒可以请求2次 private RateLimiter rateLimiter = RateLimiter.create(2);// private final Splitter ipAndPortSpitter = Splitter.on(":"); private class DownLoadThread extends Thread { @Override public void run() { while (true) { if (rateLimiter.tryAcquire(1, 500, TimeUnit.MILLISECONDS)) {// 500毫秒等待令牌桶的释放,guava限流器基于令牌桶算法 HttpClientContext httpClientContext = HttpClientContext.create(); PoolUtil.disableDungProxy(httpClientContext); String s = HttpInvoker.get(url, httpClientContext); logger.info("IP请求结果:{}", s); LineIterator iterator = new LineIterator(new StringReader(s)); while (iterator.hasNext()) { String line = iterator.nextLine(); System.out.println(line); if (CommonUtil.isPlainProxyItem(line)) { addProxy(line); } } } else { logger.info("请求过于频繁,放弃本次请求"); CommonUtil.sleep(500); } } } } public U5IpSource() { // for (int i = 0; i < 2; i++) {//发现一个线程就够了 pool.execute(new DownLoadThread()); // } } private void addProxy(String line) { List<String> strings = ipAndPortSpitter.splitToList(line); AvProxyVO avProxyVO = new AvProxyVO(); avProxyVO.setIp(strings.get(0)); avProxyVO.setPort(NumberUtils.toInt(strings.get(1))); lock.lock(); try { cache.add(avProxyVO); } finally { lock.unlock(); } } /** * 无忧代理提取地址 */ private static String url = "http://api.ip.data5u.com/dynamic/get.html?order=c7a31d45acd98e81d87655aa5d57baf9&random=true"; @Override public List<AvProxyVO> importProxy(String domain, String testUrl, Integer number) { List<AvProxyVO> ret = Lists.newArrayList(); lock.lock(); try { int i = 0; Iterator<AvProxyVO> iterator = cache.iterator(); while (iterator.hasNext()) { if (i < number) { i++; ret.add(iterator.next()); iterator.remove(); } else { break; } } } finally { lock.unlock(); } return ret; } @Override public void feedBack(String domain, List<AvProxyVO> avProxies, List<AvProxyVO> disableProxies) { } @Override public List<AvProxyVO> allAvailable() { // 不支持在预热的时候使用无忧代理,因为预热会浪费IP资源 return Lists.newArrayList(); } }