如何在PHP中实现服务器发送事件?

9
我使用PHP和while循环设置了一个服务器发送事件脚本,我不想让脚本一直关闭并重新轮询,所以我把它都放在了一个while循环中。
问题是脚本会卡住,所以我放弃了这种方法,改用了node.js websocket后端。
我的问题是,如果我回到制作服务器发送事件php脚本,该如何实现呢? while循环似乎行不通,因为它会挂起脚本。如果只是每秒连接和断开,那么与长轮询没有什么区别。那么如何创建一个PHP脚本,在不挂起的情况下发送SSE消息?

你可以在循环中加入 sleep() 来放松它。 - Musa
这个例子有什么问题吗? https://developer.mozilla.org/en-US/docs/Server-sent_events/Using_server-sent_events#Sending_events_from_the_server - Luca Rainone
@chumkiu 我已经尝试过了,但它卡住了。 - Naftali
@chumkiu 和 set_time_limit(0) - Naftali
你是否开启了输出缓冲或mod_deflate? - Musa
显示剩余2条评论
1个回答

5

您似乎遇到了PHP输出缓冲的问题。尝试在while循环的末尾添加以下行:

ob_flush();
flush();

这将禁用输出缓冲。 编辑 你还可以在一定时间后终止脚本(例如10分钟),以减少服务器负载。
我为您创建了一个库,让您可以轻松地完成这项任务。在这里查看。 第二次编辑 您是否有反向代理,如nginx或varnish?这可能是原因之一,因为代理尝试缓存输出内容,但SSE脚本永远不会结束,直到您停止它,因此整个事情都会挂起。其他捕获输出的东西可能会产生类似的结果,如mod_deflate。 第三次编辑 如果您有反向代理,可以尝试关闭缓存以使SSE正常工作。
PHP中还有其他禁用输出缓冲的方法。请参阅下面的代码:
<?php
for($i=0;$i<ob_get_level();$i++){
    ob_end_flush();
}
@apache_setenv('no-gzip',1);
@ini_set('implict_flush',1);
ob_implict_flush(true);

1
这与我对类似问题给出的答案是一致的:https://dev59.com/t1vUa4cB1Zd3GeqPtGiV#8660897 - igorw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接