[开发技巧]利用openresty来优化php-fpm的长轮询

Posted PHP技术大全

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[开发技巧]利用openresty来优化php-fpm的长轮询相关的知识,希望对你有一定的参考价值。


 

对于长轮询场景是比较常见的,客户端同步的不断的在同步请求,而服务端根据请求来决定是否响应或者hold请求以继续检查数据.


    由于php-fpm是单进程单线程的,一个进程同时只能处理一个请求,所以对于这种长轮询的场景,需要启动特别多的php-fpm进程来应对高的并发,这是特别浪费资源的,因为大部分请求都是hold在服务器上。

    现在我们用openresty来轮询php-fpm,php-fpm会很快的处理完成,不会hold住,减少了php-fpm的压力,配置文件如下:


location ~ /longpolling(/.*) {
                content_by_lua_block {
                        local request_uri_without_args = ngx.re.sub(ngx.var.request_uri, "\\?.*", "")
                        request_uri_without_args = ngx.re.gsub(request_uri_without_args,"/longpolling","")
                        local url = {request_uri_without_args}
                        local args = ngx.req.get_uri_args()
                        local query = ngx.encode_args(args)
                        if query ~= "" then
                                url[#url + 1] = "?"
                                url[#url + 1] = query
                        end
                        url = table.concat(url)
                        for i = 1, 3 do
                                local sleep = 1
                                local res = ngx.location.capture(url)
                                for k, v in pairs(res.header) do
                                        if type(v) == "table" then
                                                if k == 'sleep' and v == 0 then
                                                        ngx.header[k] = table.concat(v, ",")
                                                        sleep = table.concat(v, ",")
                                                end                                        else
                                                if k == "sleep" and v == "0" then
                                                        ngx.header[k] = v
                                                        sleep = v
                                               end
                                        end
                                end                                if sleep == 1 then
                                        ngx.sleep(1)
                                else
                                        ngx.say(res.body)
                                        break
                                end

                        end                }
        }



    

    将url中以”longpolling”开始的请求转换为长轮询.比如:/longpolling/aa 实际访问是/aa. 长轮询总共时间是3秒,每次停止一秒,根据php-fpm响应头sleep来决定是否输出还是继续轮询.PHP代码如下.

  

<?php
header('Content-type: application/json');$time = $_GET["time"];$data = get_new_data($time);if ( $data ){
        header('sleep:0');
        echo json_encode(array("data"=>$data));}else{
        echo json_encode(array("data"=>""));}

 这样我们就做了一个相对通用的仅支持get请求的优化接口。   

微信扫描二维码,关注PHP技术大全!

让知识地带无限蔓延!


以上是关于[开发技巧]利用openresty来优化php-fpm的长轮询的主要内容,如果未能解决你的问题,请参考以下文章

张超:又拍云 OpenResty / Nginx 服务优化实践

我眼中的 Nginx:深入 Nginx/Openresty 服务里的 DNS 解析

OpenResty 反向代理的用法与技巧

APISIX网关OpenResty插件开发

使用Openresty加快网页速度

利用策略模式优化过多 if else 代码