1.客户端与服务端之间协商
在应用开发中,服务端与客户端完成功能的同时也得注意应用性能,用户体验。记得在我刚进部门的时候接手一个内部应用的接口开发工作。就一个App首页,客户端不停的要求各部分的接口,我也是一个一个的快速响应。最后发现应用越来越不如意了。还准备加缓存呢。leader当时帮忙抓包分析,一眼看出问题所在。接口太多了,一个首页先拿到一个接口的数据再根据里面的数据请求下一个接口,直到所有准备就绪,客户端才正常展示。😓 后来和客户端一起协商合并了一些接口处理,App就ok了.
接口开发工作中应该与客户端协商好接口。具体是情况而定:
1.首页,分类页,App一键切换的页面进可能使用较少的接口提供数据(通过不同字段区分各组件所需的数据)
2.客户端有时请求的可能只是一个配置信息。但是却没有正确的请求时机。这个也可以考虑和别的接口进行合并处理
2.使用curl_multi请求第三方服务
今天看到同事接手的一个项目出问题了。上去一看,一个接口依赖7,8个接口。每步都是串行处理,更6的是还有一个foreach里面不知道有多少个curl访问。php-fpm不支持fork并发处理,在使用没有支持异步处理的框架的时候。我们可以使用curl_multi并发请求依赖服务。之前串行处理1s,可能现在只需要100ms就可以响应了。像下面直接传入多个url,得到Arr[url_key]=Response 的数组。自己合并就行。也可以适当加入重试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| private function getMultiUrlContents($urls, $timeout = 1) { $mh = curl_multi_init(); $chArray = array(); foreach ($urls as $i => $url) { $chArray[$i] = curl_init($url); curl_setopt($chArray[$i], CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($chArray[$i], CURLOPT_RETURNTRANSFER, true); curl_multi_add_handle($mh, $chArray[$i]); } do { curl_multi_exec($mh, $running); curl_multi_select($mh); } while ($running > 0); $res = array(); foreach ($urls as $i => $url) { $res[$url] = curl_multi_getcontent($chArray[$i]); } foreach ($urls as $i => $url) { curl_multi_remove_handle($mh, $chArray[$i]); } curl_multi_close($mh); return $res; }
|
3.使用redis管道
同样在请求redis的时候也可以使用管道合并请求。
未合并前:请求数量由count($keys)决定
1 2 3
| foreach ($keys as $v) { $all[$v] = $redis->hgetall($v); }
|
合并后:只有一个请求
1 2 3 4 5
| $redis->multi(Redis::PIPELINE); foreach ($keys as $v) { $redis->hgetall($v); } $all = $redis->exec();
|
4.尽量使用join
有时要同两个不同表里面获取关联数据。直接join就行
1
| select B.id from A left join A on A.id=B.Aid;
|
并非下面的操作:
1 2 3 4 5
| list = select id from A; for id in list do select id from b where Aid=id done
|
总结
> 接口开发中合并请求直接带来的是效率,响应速度。但是在实现上开发者必须多一下处理。像提到的第一点中不光在技术上处理,更在设计上多思考。