2

我正在使用 RApache 作为 SSE(服务器发送事件)和类似的(长轮询、彗星等)后端进行测试。我似乎被困在如何刷新我的输出上。可能吗?

这是我的测试 R 脚本:

setContentType("text/plain")

repeat{
    cat(format(Sys.time()),"\n")
    #sendBin(paste(format(Sys.time()),"\n"))
    flush(stdout())
    Sys.sleep(1)
    }

我的 Rapache.conf 条目是:

<Location /rtest/sse>
    Options -MultiViews
    SetHandler r-handler
    RFileHandler /var/www/local/rtest/sse.r
</Location>

我使用 wget 或 curl 对其进行测试:

wget -O - http://localhost/rtest/sse
curl http://localhost/rtest/sse

两者都只是坐在那里,这意味着没有发送任何内容。

usingsendBin()没有改变, using 也没有flush()

如果我更改repeatfor(i in 1:5),它会在那里停留 5 秒,然后显示 5 个时间戳(相隔一秒)。所以,我相信其他一切都运行良好,这纯粹是一个缓冲问题。

更新: 5 个月后用新的眼光看待这个问题,我想我可以更清楚地描述这个问题:问题是 RApache 似乎正在缓冲所有输出,并且在 R 脚本退出之前不发送任何内容。为了对流式传输有用,它必须在每次flush()调用时将数据从 Apache 发送到客户端,即当 R 脚本仍在运行时。所以,我的问题是:有没有办法让 RApache 表现得像那样?

更新 2我尝试flush.console()在之前或之后添加,flush(stdout())但没有区别。我也试过setStatus(status=200L)在顶部。我尝试SERVER$no_cache=T;SERVER$no_local_copy=T;在脚本的顶部。再次没有任何区别。(是的,这些都不应该有帮助,但尝试永远不会有坏处!)

以下是 PHP 在作为 Apache 模块运行时如何实现刷新的链接: http://git.php.net/?p=php-src.git;a=blob;f=sapi/apache2handler/ sapi_apache2.c #l290 我认为关键是有一个对ap_rflush(r). 我猜 RApache 没有ap_rflush()打电话。

4

1 回答 1

1

您传递了错误的 MIME 类型。尝试改变

setContentType("text/event-stream")

编辑1:

这是我在下面的评论中提到的尝试(仍然不成功)在Rook.

<%
  res$header('Content-Type', 'text/event-stream')
  res$header('Cache-Control', 'no-cache')
  res$header('Connection', 'keep-alive')
  A <- 1

  sendMessage <- function(){
    while(A<=4){
      cat("id: ", Sys.time(), "\n", "data: hello\n\n", sep="")
      A <- A+1
      flush(stdout())
      Sys.sleep(1)
    }
  }

-%>

<% sendMessage() %>

while循环条件应该总是,TRUE但我遇到了同样的问题,所以我不得不做一个有限循环......

好消息是我确实有数据到达浏览器。我可以通过查看开发人员工具Content-Length中的Response Header部分来判断。上面的代码显示为 114,然后您将“Hello!”中的“Hello”改为“Hello”。它会说 118。

js代码是:(你也需要JQuery)

$(document).ready(function(){

  $("button").click(function(){

    var source = new EventSource("../R/sse.Rhtml");

    source.onopen = function(event){
      console.log("readyState: " + source.readyState);
    }

    source.onmessage = function(event){
      $("#div").append(event.data);
    };

    source.onerror = function(event){
      console.log(event);
    };

  });


});

所以,本质上

1)连接打开(readyState 1)

2)缓冲仍然存在

3)数据(缓冲后)到达浏览器,但在正确接收它们时发生错误。

EIDT2:

有趣的是,在 brew() 上面的 .Rhtml 文件中,输出没有被缓冲。Web 服务器(R 内部和 Apache)中必须有一个配置来缓冲数据流。

作为旁注,flush甚至不需要,cat的输出默认为stout(). 所以选项是:

  1. 网络服务器配置
  2. ob_flush();我见过的任何 PHP 实现中总是使用的 PHP 的 R 等效项。是例子
于 2013-10-25T17:31:51.620 回答