一起养成写作习惯!这是我参与「掘金日新计划·4月更文挑战」的第14天,点击查看活动详情。
我们常常听到JVM调优,数据库性能优化,网络性能优化,可能最后考虑的才是API层的性能优化,但往往API层的优化才是效果最显著的。按照我的经验,往往一个比较重的API可以有数倍,甚至数十倍的优化空间,而这些基本是API层的数据优化实现的。性能优化有些人会理解为加速,然后通过加索引,加缓存实现,算是优化的一种,但很多时候这种带来的提升可能只有20%左右。根据我做API性能优化的经验,大概有下面几种方法论与实践。
转移数据
有些比较重的创建业务需要执行的操作往往十分繁重,要插N张表,推送N条消息事件等等。前端默认情况下要等服务端的返回,这就很容易阻塞,前端会一直转圈。这里的方法叫数据转移,就是把大部分的逻辑异步处理,而且不建议用线程池,直接发到消息队列中,自产自销。那前端需要的数据怎么办呢?这些数据一般会依赖服务端创建完成后产生的id。
- 如果是移动端,推送端做本地化改造,不再依赖同步的api结果,等待服务端推送
- 如果是web端,轮询服务端结果,不阻塞用户操作 在服务端接到请求后,可以立刻给前端返回200,然后按照以上2种情况分别异步告知结果。这样用户体验会急速上升,失败率和超时的情况会大幅降低。为什么不建议用线程池,因为节点重启时数据必丢,重试的机会的都没有。外部的消息队列也是一种临时存储,可靠性比线程池强很多。
精简数据
如果有些数据实在无法转移,可以在业务上做一些精简。比如,一个比较大的API拆碎,在保证主流程的情况下,增加前端的请求次数以换取更快的响应速度。不记得是什么一个理论说要做到接口的功能单一,正好运用在当前的场景。如果就是整体提交呢?比如电商的购物车几百件商品,全选提交创建订单呢?这种情况能做的是约定这种提交只提交必要的skuId,后端接到这样一个id json之后用上面一种办法去转移处理,不做实时刷新,等用户支付完成进行返回时,数据早已处理完毕,不会阻塞用户的操作。