php接口优化:合并请求

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

总结

> 接口开发中合并请求直接带来的是效率,响应速度。但是在实现上开发者必须多一下处理。像提到的第一点中不光在技术上处理,更在设计上多思考。