java系统如何做业务性能优化


前言


java系统如何做业务性能优化_缓存


基本上每个系统都有一个在整个生命周期都需要讨论的话题“性能”。在业务初期,“野蛮生长”是第一要务,只要能满足用户性能,堆机器、堆人力、堆数据库等,能直接解决的都无需上升到专门的优化专题。


经常听到的一句话就是,机器性能的提升,很少有人去关注系统调优了。当然,在服务器性能飙升导致工程师越来越少关注底层优化逻辑。



业务性能优化


那么为什么还要那么关注业务性能优化? 一方面,时刻保持性能优化,在技术方案设计期间、在编码期间、在上线运行期间、在业务维护期间,都应该追求极致的体验,可以降低系统消耗节省成本,可以节省用户时间提升用户效率。

另外一方面,性能优化应该是工程师自身的一种基本素质。系统保持相对优化状态,对于稳定性、效能都是有着重要影响。


性能优化方法论


这里简单介绍一下我对性能优化的看法。






工具化

要保证能快速定位系统的瓶颈,就应该有一套合适的工具帮助快速定位到性能薄弱点。那有一套调用链的整体观测方法,就能轻易实现这个目的了。

google公司的Dapper就是一套分布式下的跟踪系统,具体论文:http://bigbully.github.io/Dapper-translation/


分布式跟踪链路


基本上大型互联网公司都会基于Dapper实现一套自身的分布式链路系统,通过这个系统的调用链,就很容易分析出系统在每个接口和模块上的耗时,进而可以更清晰的定位接口,进一步分析代码查看其RT耗时及制定出相应的优化方案。


java系统如何做业务性能优化_缓存_02


如上图所示,阿里云提供的鹰眼能力,可以看到在每个应用上的调用耗时。


spring调用拦截

上面说的,是可以做到系统间的调用分析,对于单个应用来说,可能使用应用内部的一些拦截器来实现整体调用情况分析,可能会更为高效、具备针对性。


java系统如何做业务性能优化_复杂度_03


以上是我用的springaop的拦截器,可以打印出每个bean的消耗。进而可以分析具体某个bean的方法耗时已经耗时在哪个逻辑里。


最佳实践

通常来说,每个优化都是要CASE BY CASE的,但是从经验上来说,有几个优化方法是屡试不爽的,也基本上可以覆盖80%的场景。

批处理

很多业务场景,都需要有列表页,比如商品列表、用户列表、订单列表等,如果使用单接口的话,往往就需要循环取数,RT则容易就变成了O(N),用批处理则可以将取数优化成O(1)。经验上来看,一次内存计算1毫秒已经顶天了,但是一次RPC至少10毫秒左右。


java系统如何做业务性能优化_缓存_04


从实际调用来看,一次北京到上海的RT耗时大约在60毫秒左右。因此解决RPC调用是全部优化需要首先考虑的一个问题。


缓存处理

只要满足数据非强一致性,则可以使用缓存来降级,减少大量的DB和内存计算。比如商品详情,基本上是不会有什么变化,因此商品数据无需频繁去DB中取,我们只要将商品对象缓存起来,直接取缓存数据即可。缓存还有更多的用法,比如用作临时存储等。当然缓存还有数据一致性的问题、多级缓存的问题,这里就不再赘述,后续将对缓存重点再讲解一波。缓存的RT一般1毫秒左右,接口RT则一般至少10毫秒以上,因此用缓存空间来换取时间还是稳赚的。


异步处理

异步处理相对前面一些措施来说会比较复杂一些,首先需要对业务理解透彻,哪些是可以拆分成异步化处理的,哪些是必须同步处理的,其次是要对异步有深刻理解,异步化本身相对同步来说,会增加一个复杂度。以下是同步转异步的伪代码。

java系统如何做业务性能优化_性能优化_05


java系统如何做业务性能优化_缓存_06


当然,异步是有代价的,可以说是一种用空间换时间的办法,同时,异步的编程复杂度也会高很多。这里大家可以看看rxjava,后续会继续介绍rxjava在生产上的最佳实践。


非必要情况下,还是慎用异步的编程模式,但是架构上可以采用异步的模式,比如支付成功后发送用户消息、调用物流接口,则可以用系统消息来解耦。



总结

性能优化是一个业务持续集成类似的模式,也是需要持续做性能,性能优化是伴随业务生命周期的。优化的方式和角度都很多,这里只是总结出我在做中大型系统的自己的思考。