如何刷新RApache中的当前输出?

时间:2013-05-08 03:23:00

标签: rapache

我使用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

两者都坐在那里,这意味着没有发送任何东西。

使用sendBin()没有做任何更改,也没有使用flush()

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

更新: 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模块运行时如何实现flush的链接: http://git.php.net/?p=php-src.git;a=blob;f=sapi/apache2handler/sapi_apache2.c#l290 我认为关键点在于呼叫ap_rflush(r)。我猜测RApache没有进行ap_rflush()通话。

1 个答案:

答案 0 :(得分:1)

您传递的是错误的MIME类型。尝试使用

进行更改
setContentType("text/event-stream")

EDIT1:

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

<%
  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”。它会说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)中必须有一个缓冲数据流的配置。

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

  1. Web服务器配置
  2. PHP ob_flush();的R等价物,它总是在我见过的任何PHP实现中使用。 this就是示例