如何减小接口响应时间

如何减小接口响应时间

Premature optimization is the root of all evil.java

  — Donald Knuth缓存

对于程序优化,我一直采起保守的态度,除非万不得已。可是随着业务的不断发展,程序愈来愈复杂,代码越写越多,优化彷佛是终有一天会到来的事情。安全

那么对于一个典型的后台服务接口,咱们能够从那些方面入手进行优化呢?服务器

接口拆分

接口垂直拆分

垂直拆分能够简单理解为微服务化,把一个大而复杂的服务拆分红多个相互独立,职能单一的服务,单独部署。 更细粒度拆分的好处是,能对某个具体的微服务进行特殊优化,以最大的投入产出比来解决整个服务的性能。 垂直拆分还有一个好处是,对于非必须的接口,能够很方便的进行降级处理,把坏影响隔离到核心逻辑外部。 最容易想到的优化办法是把某个对总体性能有决定性影响的微服务接口进行水平扩容。网络

注意: 拆分后一定会增长外部接口调用,多少会有些额外开销,可是对于有限几个调用,拆分的仍是值得的。并发

接口水平拆分

这里说的水平拆分必定不是把一个接口部署更多份,由于这样只能解决接口的容量问题,可是不能减小接口的响应时间。 水平拆分能够简单理解成mapreduce模型,把整个计算逻辑或者数据平均分配到集群中的N个服务器去,而后由一台机器去并发调用并作结果合并。 理论上这种方式能把响应减小到1/N+合并+调用开销的时间。异步

注意: 一个问题须要考虑的是,若是并发调用的接口返回的数据量比较大,可能会对合并机器的网络负载和数据序列化(CPU)有必定影响。分布式

缓存

接口缓存

一个有着复杂逻辑或者大量计算数据的接口,能对整个结果进行缓存再好不过了。缓存针对不一样的场景会有多种策略,对于有大量并发请求的场景, 推荐一个方案:一种基于“哨兵”的分布式缓存设计,不会有损失第一个用户,也不会有定时更新缓存的额外开销。微服务

本地缓存

本地缓存有两种场景,对于相似字典类型的数据,能够静态化后放入内存,定时去刷新或者采用通知机制去更新。性能

还有一种场景是用ThreadLocal缓存重复内部计算与重复的对象建立; 对于链路比较长或者循环比较深的接口,ThreadLocal减小重复计算和对象建立,从而下降RT和节约内存。

注意: 在有内部并发的地方使用ThreadLocal必定要注意不一样线程间的数据同步。主线程的ThreadLocal数据和每一个并发子线程的ThreadLocal数据要同步好。

内部优化

非核心流程异步化

相似于发消息,写日志,更新缓存等不会影响接口准确性的非核心流程,能够采用异步方式进行处理,不阻塞主计算逻辑处理。

内部并发

若是进行水平拆分后,并发调用IO较大,能够考虑换成内部并发解决IO问题。若是内部并发涉及到每一个线程更新同一个集合数据,不用忘了使用线程安全的集合。 这里有一个并发更新HashMap的case:并发环境下HashMap引发full gc排查

总结

优化必定不是一蹴而就的,整个优化过程是一个统计-->方案-->验证的闭环,须要不断试错,不断挖掘,最终达到预期。

相关文章
相关标签/搜索