当前位置: 首页 > 工具软件 > PHP SSE > 使用案例 >

sse php,在nginx下利用php配置SSE的正确方法

沈良策
2023-12-01

SSE简介

SSE是Server-Sent Events的缩写。一般状况下,是咱们的浏览器向服务器发起请求后,服务器响应,而后关闭链接。为了可以保持通讯,以便在服务器有事件发生时主动通知浏览器,后来人们又发明了不少技术,包括websocket等。可是websocket对于代码改动较大,因此又出现了SSE,它的特色是基本不用改写原有的逻辑,只是增长一些小的改动就能实现服务器与客户端之间的长链接,达到服务器主动通知客户端的目的。javascript

可是我在按照网上教程真正去在nginx环境下实现SSE时,颇费了一番周章,留在这里,以便有同窗遇到相似问题时参考。php

客户端

SSE的主要原理是由客户端,也就是浏览器里的javascript发起一个相似于ajax的请求,但和ajax不一样的是,这是一个一直保持的长链接,一旦请求创建以后,客户端开始安静地等待服务端向它发回数据,这个链接能够保持很长很长时间。java

因此客户端的代码很简单:nginx

source = new EventSource('http://api.server.com/path/file.php?param=value');

source.onmessage = function (event) {

json = JSON.parse(event.data);

... 后面是你处理数据的部分 ...

};

不用担忧断掉,即便断掉的话,客户端会在断掉以后的3秒以后自动再次从新向服务端发起链接请求,并且这个从新链接是浏览器自动帮助咱们实现的,咱们在编程时能够彻底不去考虑它。web

服务器端

php部分

header('Access-Control-Allow-Origin: http://www.server.com');

//发送SSE应答

header('X-Accel-Buffering: no');

header('Content-Type: text/event-stream');

header('Cache-Control: no-cache');

$old_md5 = '';

//执行100次,每次睡眠3秒钟,总共300秒,也就是5分钟

for ($i=0; $i<100; $i++) {

//保持一个长链接,每隔3秒钟回答客户端一次

$o_data = 你的数据;

$str_return = json_encode($o_data);

$md5 = md5($str_return);

if ($md5 != $old_md5) {

//若是内容发生了变化,则推送,不然没必要推送,以节省网络流量

echo 'data: ' . $str_return . "\n\n";

$old_md5 = $md5;

}

ob_flush();

flush();

//等待3秒钟,开始下一次查询

sleep(3);

}

逐行分解一下:ajax

这三句话必不可少:编程

header('X-Accel-Buffering: no');

header('Content-Type: text/event-stream');

header('Cache-Control: no-cache');

其中的第一句话,是配置nginx必需的。由于nginx缺省会对全部来自php的数据做缓存,它必定要等到全部数据所有写进缓存后才一股脑发给客户端,而咱们要创建的是一个很长的链接,这个链接过程当中随时可能要发送数据,不须要缓存,因此这里必须经过X-Accel-Buffering告诉nginx你对我这段代码不要给我作缓存,不然你会在客户端等很长很长时间却一个字符也收不到。json

注意后面那个100次的for循环,网上几乎全部的例子里在这里都会使用while(1)的一个无限循环,但我我的的经验偏偏相反,在这里应该是一个for循环,而不是while循环。为何呢?由于咱们必须使得整个程序的执行时间可控,若是你用for循环100次,每次sleep 3秒钟的话,整个脚本的执行时长也就是在5分钟左右,而若是你使用while无限循环的话,整个时间会几乎是无限长。有的同窗可能会说我在php.ini里设置了max_excution_time是60秒钟啊,很好,我一开始也是这么认为的,可是:sleep(3)的时间不算在内!因此你能够想象一下你的脚本要执行多长时间才会结束并安静地从内存中退出去?api

nginx设置

最后,还须要配置nginx,只须要一句话,在你的nginx.conf的location里:浏览器

fastcgi_read_timeout 600s;

这是因为nginx在和咱们的php-fpm进行通信的时候,这个地方的缺省值是60,若是它等了60秒,结果php-fpm一个字符也没有送过来的话,nginx会强行停止与咱们的程序的链接,但咱们的程序实际尚未执行结束,这时候js客户端发现链接断了,就会自动重启一个新的链接,结果咱们服务器端的资源很快被耗尽了。在这里设为600秒的意思是告诉nginx,即便个人php代码一个字符也不给你发送,你也必须老老实实呆够10分钟才能够退出。而其实是,还记得咱们前面的for循环吗?咱们会在100次等待3秒后,也就是5分钟内退出咱们的php脚本执行,不会凑够10分钟的。因此这里很安全。

 类似资料: