SSE 服务端向客户端推送

传统的ajax都是由客户端主动去请求,服务端才可以返回数据

而sse是建立一个通道,并且在断线后自动重连,由服务端去推送,不需要客户端去主动请求,只需要建立通道

websocket是双向通信 客户端可以利用通道推送数据给服务端 服务端也可以推送数据给客户端

在有些场景,例如用户端调起支付,没有返回支付通知,需要向后端请求,获取这笔订单的支付结果
例如微信公众号内使用支付宝支付,是调不起来的,只能引导用户浏览器打开,由浏览器调起支付宝客户端进行支付
这时候微信公众号内的页面,是不知道支付结果的

常规操作是ajax 心跳查询 每隔一秒或者两秒向后端请求,获取这笔订单是否是支付成功的
但是性能很差,大量的请求,数据库压力会很大

用sse建立通道,因为这里客户端不需要向服务端推送数据 只需要获取,而且sse可以自动断线重连
服务端只需要每秒查询一次数据库,推送数据给客户端即可 但是这样性能也很差,还是要查库

最好的方法是在支付回调处,修改数据库订单状态的同时,向redis插入 例如order_pay_订单号 后端查询订单状态的时候,就无需就查库,直接去redis查询,如果有这个键,则支付成功,如果没有,则继续查询,这样查询支付结果,不需要查库操作,只需要查询redis,性能很高

客户端demo

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <link rel="stylesheet" href="">
</head>
<body>
    <div id="result">
        
    </div>
</body>
<script src="https://cdn.nikm.cn/js/jquery.js"></script>
<script>
    if(typeof(EventSource) !== "undefined") {
        var source = new EventSource("./test17.php");
        source.onmessage = function(res){
            var data = JSON.parse(res.data);
            console.log(data);
            $('#result').html("<p>" + data.msg + "</p>");
        };
    }else{
        console.log('您的浏览器不支持SSE');
    }
</script>
</html>

服务端demo

<?php
//设置SSE的header头部
header('X-Accel-Buffering: no');
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
ob_end_clean();//清空缓冲区并关闭输出缓冲
ob_implicit_flush(1);//每当有输出,例如echo的时候,就直接传输,不在缓冲区
//设置死循环,并sleep
while(true){
    //设置要返回的数据
    $data = [
        "status" => 1,
        "msg" => '北京时间'.date('Y-m-d H:i:s'),
    ];
    //按规则去拼接
    $str = 'id: '.time()."\n";
    $str .= "event: message\n";
    $str .= "data: ".json_encode($data)."\n\n";
    echo $str;
    sleep(1);
}
 ?>
Last modification:December 24th, 2019 at 03:06 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment

简爱博客