从10s到300ms的接口优化,我做了哪些事
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从10s到300ms的接口优化,我做了哪些事相关的知识,希望对你有一定的参考价值。
小程序的接口刚写完时,一个接口的调用时间大概是700ms左右,100并发的100请求的压测结果是9s,用的都是项目的底层方法(有缓存),框架是ci.而上线城市服务的三星基准是500并发500ms以下,远远不达标,于是乎开始了漫长的优化.在此记录一下从10+s优化到300ms的过程.
- 用xhprof分析了代码,发现ci的cache的redis驱动做了这样一件事,耗费了大量的性能
-
$serialized = $this->_redis->sMembers(‘_ci_redis_serialized‘); if ( ! empty($serialized)) { $this->_serialized = array_flip($serialized); }
ci的redis驱动初始化程序里有这样一段代码,这段代码的含义是将"_ci_redis_serialized"这个集合中的所有成员都取出来.然后反转键值对.而_ci_redis_serialized这个集合对于ci的涵义就是为了记录序列化后的数据.因为ci的cache可以把任何数据都放入cache中,包括字符串,数组,对象等,而redis只能存储一种数据格式.所以就需要将数组或者对象序列化存入redis中(当然如果你不打算存储对象完全可以用json格式来存储数据).问题就出在这里,一个项目的key往往是数量级的增长的,像我们就有16w的key是经过序列化存放在这里的(除了数据缓存,还有大量的用户session数据也是需要序列化的),在大量的cache操作下,这个过程就耗费了大量的性能.解决方案是:既然用了集合,直接用SISMEMBER来判断这个集合中是否有这个成员就行了,redis的内置方法性能是非常好的(好到可以忽略)这次优化后从10+s下降到了3s左右.
-
- 在获取数据的底层方法上,在小程序再封装一层
- 只提供给前端必要的字段
- 这两个步骤让时间下降到了1s+,很简单的逻辑,减少不必要的数据传递,减少冗余数据.
- 去除session中的_get_lock,这个是防止两个进程同时写一个key,因为基本发生不了所以先去除
- 不经过service层,直接访问数据库,为了能让service层(数据层)能单独部署,所以内部访问模型是通过curl来请求的.现在改造成直接通过ci的model来访问(也就是直连数据库了)
- 这两个步骤让时间下降到了600~700ms,基本上没有太大的优化.
- 最后的优化是apacache,让服务器来缓存php文件.
- 最后这个步骤让时间优化到了300ms,单独访问一次接口只要30ms左右
最后的结果就是小程序的压测结果通过啦~
以上是关于从10s到300ms的接口优化,我做了哪些事的主要内容,如果未能解决你的问题,请参考以下文章
一次SQL查询优化原理分析(900W+数据,从17s到300ms)
一次SQL查询优化原理分析(900W+数据,从17s到300ms)