Java中,有一个for循环调用网络api很耗时,请问如何减少耗时?

如题,早上看了一大堆线程池优化的,没试出来
关注者
111
被浏览
94,909

30 个回答

这太正常了,一次网络调用,就算延迟100ms吧,你循环个10次就是1s(这还是完全理想,不考虑插队,网络抖动一类的问题)。

首先先问自己为啥要用for调用N次api,这是N个一样的api还是不一样的api?这个操作对用户来说是“1个操作”还是“N个操作”?下游api能提供某种把N个api合并成批量的api吗?或者下游有某种pipeline机制可以合并这个N次请求到一次网络请求吗?没有,能做一个吗?如果底层数据模型无法支持N个api同时做,是否可以改造底层数据模型呢?

此外,如果要求非常低的延迟,用RPC这种形式本来就是不对的。可以考虑改造了。参考游戏服务器的做法。

此外指出用多线程不一定有效果,多线程是并发了,你能确保他们真的并行吗?真的并行,同时发出去了的请求,你确认真的他们各自排队造成的延迟是差不多的吗?用多线程的各自发不同的请求的结果是,这一次请求的延迟取决于被处理最慢的那个请求。而那个最慢的请求是不是有可能排队很久呢?是不是直接就丢了,于是需要重新发?如何判断丢了?丢了1个,其他N-1个的结果咋办?是不是开始烧脑了?

另外这个效果一定就比循环N次强吗?压测下看看。

最后,这事和Java一点关系都没有。看看网络的书~

1 改api,让api支持batch批处理,这样你可以一次发几十上百个请求。

2 客户端多线程并行发送请求,你可以用线程池,也可以用异步call

3 你把客户端部署到几十台机器上

4 同时使用1,2,3,直到服务器挂了为止。。。。

这其实是一个典型的对性能优化没有入门的提问。

性能优化的前提,是找到性能瓶颈。 能理解这句话,你就已经一只脚踏到棺材板,哦不,踏到性能优化的门槛里了。


在这个回答里,For循环调用Api耗时,这是一个性能瓶颈,问题不大。

那接下来的方案是什么呢?


1 异步:如果你的API只是请求不用返回,异步调用是最简单的方式,如果你的API需要有返回,但只果不是同步的关系,你还是可以用异步。扔给一个线程程去解决就完事了。

2 批量:API的调用很大一部分在于TCP三次握手的链接,所以如果能够批次处理数据,那么性能提升杠杠的,当然,问题也在于是,如果出错了怎么办?

从这两个方案里能看出什么呢?

性能优化不是一个通用的方案,要结合实际业务场景,再给出对应的优化方案

通用性的原则是最基础的,你需要的是在基础的性能优化方案之上,结合实际的应用场景,给出最合适的方案。


还有, 性能优化是需要有优化目标的 。这个道理如果能懂,那么你已经一半身子挤进来了。

为什么要有目标?因为目标不同,你的方案也不同啊。


比如说,你要从10秒优化到5秒,和优化到20MS,那方案肯定不一样。

就以这个方案为例,如果你非要20MS解决,那就拉专线嘛。


重新总结一下性能优化的三板斧,弄懂这个,你在性能优化的道路上可以越走越远了,这比掌握一两个技巧更重要。


1 性能优化的前提,是找到性能瓶颈。

2 性能优化不是一个通用的方案,要结合实际业务场景,再给出对应的优化方案

3 性能优化是需要有优化目标的


嗯,回答内容也会收录到黑塔职业规划小程序里去。

1.单步变批量

2.同步变异步

3.cache是万能药

具体一点来说就是,看能否使用下游服务的批量获取接口,减少io次数;如果请求之间没有依赖,使用线程池异步的发起请求,用Future收集所有结果;如果请求结果是幂等的,可以考虑加个缓存,下次就可以一次获取;