如何减少接口响应时间

remature optimization is the root of all evil.

  — Donald Knuth

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

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

接口拆分

接口垂直拆分

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

注意: 拆分后必定会增加外部接口调用,多少会有些额外开销,但是对于有限几个调用,拆分的还是值得的。

接口水平拆分

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

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

缓存

接口缓存

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

本地缓存

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

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

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

内部优化

非核心流程异步化

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

内部并发

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

总结

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

时间: 2024-10-19 11:31:12

如何减少接口响应时间的相关文章

awk分析nginx日志里面的接口响应时间

最近,有客户反应客户端卡,老板集合技术人员开会讨论,找出慢的原因,由此产生了分析nginx响应时间,由于线上环境nginx日志格式带上了引号,处理起来有点麻烦,以下是处理过程 一.nginx日志格式 log_format main '$remote_addr – $remote_user [$time_iso8601] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user

Fiddler查看接口响应时间

有时候,某些接口访问过慢,我们需要测试接口查看响应时间,从而进行优化.(由于fiddler自带的没有进行响应时间的统计,所以我们需要给他添加新的规则) 首先打开Fiddler,在菜单栏上面找到Rules->CustomRules 默认是记事本打开,我是通过复制,用vs打开 我们把下面的代码复制到 class Handlers中,如上图所示(我已经复制进去了) function BeginRequestTime(oS: Session) { if (oS.Timers != null) { ret

postman的监控接口响应时间monitor

Monitor简介1.是基于Postman集合API的灵活监控 2.监控API的正常运行时间.响应能力和正确性 3.提供监测结果的详细报告 4.对所有Postman用户每月提供1000个免费的监控请求 详细使用教程1.点击需要监控集合右侧箭头,选择Monitors,点击“Add a monitor” 2.输入监控名称“机票 Monitor”,选择运行环境“online”,定时类别我选择了分钟级的“Minute Timer”,每5分钟运行一次 3.添加成功后,点击去集合的Monitors下查找你的

(C#)日志接口请求响应时间

日志接口响应时间,记录接口请求信息,响应结果以及响应时间等.可以清楚的分析和了解接口现在. 如果一个一个地在接口下面做日志,那不是我们想要的结果.所以,我们选择做一个特性来控制接口要不要记录请求响应日志. 关键代码如下: public class LogRequestAndResponseAttribute: ActionFilterAttribute { private static string RequestLogSwitch = string.IsNullOrEmpty(Configur

接口测试总结

本文主要分为两个部分: 第一部分:主要从问题出发,引入接口测试的相关内容并与前端测试进行简单对比,总结两者之前的区别与联系.但该部分只交代了怎么做和如何做?并没有解释为什么要做? 第二部分:主要介绍为什么要做接口测试,并简单总结接口持续集成和接口质量评估相关内容. 第一部分: 首先,在做接口测试的过程中,经常有后端开发会问: 后端接口都测试什么?怎么测的? 后端接口测试一遍 ,前端也测试一遍,是不是重复测试了? 于是,为了向开发解释上述问题,普及基本的测试常识,特意梳理了接口测试的相关内容以及其

接口优化策略

对于程序优化,我一直采取保守的态度,除非万不得已.但是随着业务的不断发展,程序越来越复杂,代码越写越多,优化似乎是终有一天会到来的事情. 那么对于一个典型的后台服务接口,我们可以从那些方面入手进行优化呢? 接口拆分 接口垂直拆分 垂直拆分可以简单理解为微服务化,把一个大而复杂的服务拆分成多个相互独立,职能单一的服务,单独部署. 更细粒度拆分的好处是,能对某个具体的微服务进行特殊优化,以最大的投入产出比来解决整个服务的性能. 垂直拆分还有一个好处是,对于非必须的接口,可以很方便的进行降级处理,把坏

Delphi 的接口机制——接口操作的编译器实现过程(1)

学习COM编程技术也快有半个月了,这期间看了很多资料和别人的程序源码,也尝试了用delphi.C++.C#编写COM程序,个人感觉Delphi是最好上手的.C++的模版生成的代码太过复杂繁琐,大量使用编译宏替代函数代码,让初学者知其然而不知其所以然:C#封装过度,COM编程注定是要与操作系统频繁打交道的,需要调用大量API函数和使用大量系统预定义的常量与类型(结构体),这些在C#中都需手工声明,不够简便:Delphi就简单多了,通过模版创建的工程代码关系结构非常清晰,而且其能非常容易使用API函

设计模式之禅-接口隔离原则

个人blog 此篇博文地址:http://www.sanyinchenblog.com/?p=174 接口隔离原则: demo: https://github.com/sanyinchen/UMLDemo 接口的两种类型: (1)实例接口 (2)类接口,使用Interface定义的接口 隔离: (1)客户端不应该依赖它不需要的接口 (2)类间的依赖关系应该建立在最小的接口上 场景描述:你一日在大街上闲着无聊,在大街上喊了一句美女,结果好多女生都回过头注视你. 我们现在给美女下一个定义: (1)好

开发php接口注意点

1.制定规范 开发前一定要定好一个规范,比如要定好数据返回的通用参数和格式.关于数据格式,用的比较多的有xml和json,我建议用json,因为json比xml的好处更多. 2.精简的返回数据 接口数据因符合需要什么返回什么的原则,比如要查询某个用户的余额和注册时间,网页里面的做法可能是select * from user where uid=1,但是接口一定要select balance,regtime from user where uid=1.因为接口返回数据是要有开销的,要流量的,能少返