68%到41%:掉下去的不是成功率,是IP段的“新鲜度”
切换代理池前日成功率68%,切换后反而掉到41%。同一天、同一批10万个商品、同一份Java脚本,唯一的变量就是代理池。这组数据来自上季度经手的一个电商比价项目——每天采10万+ SKU,要抓价格、券后价和库存状态,两小时跑一轮。
我第一反应是目标站上了JS挑战,花两个晚上写了Headless方案,跑完才发现方向错了:返回码全是HTTP 200,但正文长度普遍低于8KB,商品价格字段为空。这是典型的软封——TCP握手是通的,内容被抽走了。作为日常写风控规则的人,我太清楚对面的判据:抓了500个空响应IP做归因,同一C段(/24)重复出现率37%,另有21%落在同一个ASN上。问题从来不是池子大不大,而是拿到的IP是不是别人用剩的。Java代理IP的可用率,不该看服务商首页那个99.9%,而是目标站认没认过你。
自建靶场:三种接入方式的封禁曲线
我在本地起了一个300行的检测服务,复刻平时写的风控逻辑:同一/24段5分钟内出现超过20个IP计一次风险,UA与TLS指纹不一致计两次,请求间隔方差低于0.3再加一次。然后拿三种Java代理IP接入方式各打5万请求,每万次记录一次存活率。
| 接入方式 | 首1小时成功率 | 3万请求后成功率 | 平均RTT | 成本口径 |
|---|
| 短效API提取(3分钟) | 92.4% | 68.1% | 41ms | 3.1元/万次 |
| 隧道代理(账密认证) | 94.7% | 85.7% | 28ms | 16元/天起 |
| 每请求轮换 | 88.3% | 79.5% | 55ms | 4.2元/万次 |
短效提取的短板不是慢,是复用不可控——你不知道回收的IP多久后会重新发到自己手上。每请求轮换的55ms RTT放在两小时窗口里,光握手就吃掉约12%的时间预算,10万商品模式下这个损耗很肉疼。
Java侧真正决定存活率的三个配置
多数“泄漏”不在服务商,在自己代码里。我踩过最疼的一次,是OkHttp的ConnectionPool闲着把已封IP拖回来复用,日志上看着是新请求,对面看到的是同一出口的第二次握手。
- keepAlive别设太长,60秒比默认5分钟安全得多;
- 失败重试必须换出口,在原IP上重试等于给对面送指纹;
- 只catch IOException不够,软封走的是200分支。
OkHttpClient client = new OkHttpClient.Builder()
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port)))
.connectTimeout(3, TimeUnit.SECONDS)
.readTimeout(8, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool(16, 60, TimeUnit.SECONDS))
.build();
// 200但正文过短:判定软封,摘IP换出口,绝不在原IP重试
if (resp.code() == 200 && body.length() < 8000) {
ipPool.evict(currentIp);
return fetchWithNewIp(url, retry + 1);
}
说实话,第三条是我被坑了三次才补上的。前两次只盯着异常,第三周才发现成功率是被200空页一点点磨下去的。
同量级团队可以直接抄的清单
- 先做5万请求的小流量靶场,别拿生产任务试池;
- 接入方式优先隧道,固定并发场景下弹性最好,像mayihttp.com那档16元/天的隧道,实测延迟能压到个位数毫秒;
- 业务层必须具备软封识别,正文长度阈值按页面模板定;
- 每200次请求重建一次Client,切断脏连接复用;
- 把“单IP有效请求数”写进监控,掉到均值50%以下就告警。
结论很明确:10万/天这个量级,隧道代理的存活率优势值得多付那笔钱,我跟采购争了两轮才把预算批下来。但边界也说清楚——如果你们日请求上到千万级,带宽和并发才是瓶颈,池的新鲜度反而退居次位,方案得重算。