语言:PHP
接口超时问题是一个比较常见的场景,当接口中包含有较多的数据库查询语句,并且涉及到循环执行这些查询语句时,执行时间就会变大很多,初期可能因为新表数据量少还在接受范围,当后期数据量变大后,可能就会消耗极的时间,甚至是超时。
方法一:延长可执行时间
对面这个问题,我们可以延长可执行时间,
1 | set_time_limit(30); //设置程序执行时间为30s |
但这种方式,对用户其实特别不友好。除了一些特殊场景外,并不建议无限制的延长可执行时间。特别是不要将时间设置为set_time_limit(0)无限时长,这样一旦遇到死循环情况,执行就不会结束,可能会导致大量进程堆积,极大的消耗CPU。
方法二:消息队列
通过消息队列的方式,将请求插入队列(可以借助Redis等缓存),直接返回结果。再脚本通过获取队列信息执行需要的操作。
- 优点:这样返回的速度会极快,而且内容也可以有效执行。
- 缺点:脚本如果执行失败,但之前请求已经返回成功。
- 优化:
1
2
31. 脚本完成时通过请求**回调接口**告知执行结果;(当然,脚本执行过程中的日志记录也很重要)
2. 前端收到接口返回成功信息时,展示给用户的内容"友好"调整,例如执行完成、已执行。前端提供查看结果页,及时更新状态;
3. 如果明确执行的时间是较长的,前端可以适当做一些等待动画,让整个完成等待时间有一定延长,对后续用户查看结果是友好的.
方法三:php 接口提前响应返回,然后继续执行后台逻辑
php 程序(以 php5.6 版本进行演示) 是可以在接口中,进行一些异步操作的, 不过写法有点特殊。
1. ob_end_clean()
这个是清除之前的缓冲内容,这是必需的,如果之前的缓存不为空的话,里面可能有 http 头或者其它内容,导致后面的内容不能及时的输出
2. header(“Connection: close”)
告诉浏览器,连接关闭了,这样浏览器就不用等待服务器的响应。
3. header(“HTTP/1.1 200 OK”)
发送 200 状态码,要不然可能浏览器会重试,特别是有代理的情况下
4. ob_start()
开启当前代码缓冲
5. ob_end_flush()
输出当前缓冲
6. flush()
输出PHP缓冲
7. ignore_user_abort(true)
在关闭连接后,继续运行php脚本
8. set_time_limit(0)
no time limit,不设置超时时间(根据实际情况使用)
9. fastcgi_finish_request()
这个在有用 fpm 的时候,会用到, 也是将提前返回响应,然后接下来的逻辑后台执行。
封装函数:
1 | // 异步的成功返回函数 |
深入理解ob_flush和flush的区别(ob_flush()与flush()使用方法)
php:flush()和ob_flush(),ob_end_flush()用法区别详解