
1.场景描述
现有基础数据 13w 条,需循环通过第三方 HTTP 接口获取历史数据进行分析统计,意味着要发生 13w 次 HTTP 请求。接口请求速度还比较慢,平均每次请求需要 1s,如果在单线程的情况下至少需要 36 个小时,目前我设计的是使用多线程每 3w 条作为一个任务进行请求,目前的消耗时间大概能减少到 16 小时左右,但效率还是太低了,有没有大佬有更好的解决方案的?求 Help!!
2.部署环境
系统:CentOS7
配置:单 CPU 双核
1 gaius Apr 19, 2019 1s 是网络问题还是对方处理的比较慢? |
4 2kCS5c0b0ITXE5k2 Apr 19, 2019 via iPhone @EdwardLee 感觉没啥办法。。1s 太慢了 |
5 peyppicp Apr 19, 2019 ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(100, 200, 10, TimeUnit.MINUTES, new ArrayBlockingQueue<>(100), new NamedThreadFactory("trade-thread-", true), new ThreadPoolExecutor.CallerRunsPolicy()); 然后你主线程 for 循环提交 runnable 或者 callable 任务就完事了。200 条线程应该可以了 |
7 orangeade Apr 19, 2019 via Android 换 golang 然后无脑开 goroutine ? |
8 EdwardLee OP @peyppicp 200 个线程会不会出问题啊?我试试。多线程不太会用,我是参照网上说的 IO 密集型任务应设置线程数为核心数的两倍,HTTP 请求应该属于网络 IO 吧。 |
10 xuwenping Apr 19, 2019 via Android 对方能不能也使用多线程? |
11 HuHui Apr 19, 2019 via Android 让对方提供批量查询接口 |
15 gz911122 Apr 19, 2019 用 netty 异步回调 这种性能主要是卡在网络 io 的情况下用异步再合适不过了 |
17 feiyuanqiu Apr 19, 2019 via Android 对方一个请求都能处理一秒,开几百个线程的不一下把人家服务器打死? 问问看能不能提供批量查询接口吧,估计没戏 |
18 az422 Apr 19, 2019 via Android 异步 httpclient,如 Apache 那个 httpasync 或者 vertx.client (多个实例),并设置 keepalive (双方) 当然还是批量接口靠谱 |
19 EdwardLee OP |
21 rrfeng Apr 19, 2019 via Android 你算一下对方最多能提供每秒几个 然后就写自己的并发量 取决于对方而不是自己 |
24 lhx2008 Apr 19, 2019 via Android 异步可以一下打 13 万条请求出去,对方回数据,操作系统会自动保存,然后程序可以慢慢拿返回结果。但是对方的服务器是妥妥的挂了。。 所以先压测一下,看看同时打多少条出去 |
25 MoHen9 Apr 19, 2019 via Android 数据量有多大,返回怎么那么慢?还有为什么不能自定义获取条数? |
26 JadeV Apr 19, 2019 via iPhone 对接的蛋疼事儿,并发量只能看对方接口了。。之前也碰到过,并发请求多了被对方拉黑了。。。 |
27 az422 Apr 19, 2019 @EdwardLee 是取决于对方承受能力,但跟多线程本质不同,多线程本质会阻塞的,异步不会,在对方承受能力下能增大你这边的吞吐量。 `我设计的是使用多线程每 3w 条作为一个任务进行请求,目前的消耗时间大概能减少到 16 小时左右` 像你这样设计,在对方 1s 内没有返回内你的线程是被阻塞不能干其他事的,完全浪费了性能。130000/(16*3600)约 2.25 ,相当于你 1s 才 3 个请求?要是对方能力真这样当我没说。。。 假设对方最大 qps=10000, 你可以开 10000 线程, (但是你单 CPU 双核 = =), 这种情况下还是用异步 IO 能压榨对方性能 |
28 misaka19000 Apr 19, 2019 via Android 异步操作 |
29 33and66 Apr 19, 2019 这种数据 建议生成 txt 文件 然后通过文件内容建议直接做 方法很土 但是很实用 我们现在和银行每天上千万的数据对账就是这么干 |
30 liujan Apr 19, 2019 如果是对方数据加工处理比较慢的话,是不是可以先让他每天 定时离线处理好了数据,然后你再过去拉处理后的数据? |
31 whp1473 Apr 19, 2019 每天根据你的数据定时获取对方数据,将获取的数据保存起来,用户查询时查自己库,然后缓存起来。 |
32 mritd Apr 19, 2019 via iPhone 可能这个回答不对路,但是如果这种需要大并发处理的我真的会上 golang 写,因为这样基本不需要带脑子.... |
33 xdlucky Apr 19, 2019 联系对方直接买数据 |
34 xzg Apr 19, 2019 看你响应结果是否需要,不需要就搞异步多线程。如果需要响应结果那就只能等待 1s,尝试开启多线程,实在不行部署多个服务并行发 |
35 Yourshell Apr 19, 2019 寄 U 盘吧 |
40 EdwardLee OP @misaka19000 很多都是建议异步操作的,没怎么了解过,我试试看。感谢建议 |
43 EdwardLee OP @whp1473 您建议的这种方式可能不太适合我这个场景,应该适合那种一次性响应数据量比较大的情况。目前接口并非因为响应数据量大而缓慢,所以即使定时获取也无法迈过多次 HTTP 请求这道坎,还是得想办法提高 IO 利用率 |
47 < href="/member/EdwardLee" class="dark">EdwardLee OP @xzg 业务场景是不需要实时响应的,异步应该是可行的。暂时不太了解异步,尝试了下多线程,效果还是很明显的,已经能够满足需求了。 |
48 EdwardLee OP 目前情况: 1. 单线程:耗时约 36 小时,请求稳定(效率极低) 2. 分批 3w 数据 /线程,共 5 个线程:耗时约 16 小时,请求较稳定 (效率略低) 3. 固定 30 个线程:耗时约 3.5 小时,偶有 HTTP 请求超时(效率已经能够满足,需解决部分超时异常) 4. 固定 100 个线程:测试过程因请求超时案例过多,暂不予考虑,所以未计耗时 总结: 我的业务场景属于网络 IO 密集型任务,时间基本都消耗在等待 HTTP 请求的响应,所以多线程请求还是效果很明显的,至于固定多少线程效率最高我无法确定,纯手工尝试,有科学测量方式的小伙伴麻烦指教一下。30 线程数已经能够满足业务需求,暂以项目交付为先,关于各位 V 友的建议比如异步请求之类的有空的时候再尝试。 在此感谢各位 V 友的不吝赐教 |