端到端响应式流 RESTful 服务

Igo*_*oso 4 java reactive-programming rxjs

我已经阅读了这篇文章,我不知道这是否是一个愚蠢的问题。我是反应式编程的新手。

问题很简单:假设我有一个完全反应式的后端,我怎样才能流式传输到浏览器(例如一个大文本),并在每个块来自服务器时立即将它们打印给用户?

可能我遗漏了一些重要的概念点,但我需要知道的是:我可以通过一个 HTTP GET(?或不)请求发送一小部分数据(从服务器到浏览器)吗?关键是:我可以写那些小部分,直到全部数据发送出去吗?

谢谢你的帮助。我之前确实尝试过 google,但我总是得到有关其他概念(如 websockets、长轮询、react.js)的信息,我认为情况并非如此。

编辑:我不是要求特定的 API ou 库。我只是想理解这个概念,例如:“你不能用 HTTP 协议做到这一点,句号!” 或“这与响应式编程无关,您对流的真正含义感到困惑。请参阅'something_else.js'”。

EDIT2:我使用 spring-mvc (spring-boot) 和这个方法做了一个小的休息控制器:

@RequestMapping(value = "/flush", method = RequestMethod.GET)
public void flushTest(HttpServletResponse response) {

    response.setContentType("text/html");
    response.setStatus(SC_OK);

    try (ServletOutputStream outputStream = response.getOutputStream()) {
        for (int i = 0; i < 3; i++) {
            String chunk = "chunk_" + i;
            outputStream.print(chunk);
            outputStream.flush();
            response.flushBuffer();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

}
Run Code Online (Sandbox Code Playgroud)

在浏览器中,即使使用了flushBuffer,也只有整个响应到达。经过一番研究,这可能是一个 TOMCAT 问题,我改变了我的 pom.xml,包括 undertow:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)

使用默认配置:

server.undertow.accesslog.enabled=true
server.undertow.accesslog.dir=target/logs
server.undertow.accesslog.pattern=combined
server.compression.enabled=true
server.compression.min-response-size=1l
Run Code Online (Sandbox Code Playgroud)

此时,在我的 IDE 中使用调试,每个块都在flushBuffer 之后写入。

So, I believe this could be a TOMCAT configuration. Long story short, I know there are a lot of things to help me on "streaming solutions", and thanks for all the comments, but my problem was a little bit more conceptual.

mku*_*lke 8

在 HTTP 之上有一个协议,它允许使用 HTTP 传输将服务器响应以较小的、随时可以使用的块传送到浏览器。它被称为SSE(服务器发送事件)或EventSource是关于该主题的非常完整的文章。

还有其他方法可以使用 HTTP 协议传输数据。一种这样的替代方案是 JSON 流,其中您在来自服务器的线路上写入部分响应,并在它们到达时使用 JSON 块。在消费端,一个流行的库叫做Oboe.js,在服务器端,你基本上需要在你想要发送它时或者当它可用时在响应线上写入部分数据。

对于这两种方法,Rx 可用于处理服务器端的流逻辑。您将这些部分建模为一个流(处理错误等),最终,在订阅服务器中,您将单个发射写入线路,在 Observable 完成时关闭响应。

在客户端,EventSource 事件可以包装在一个新的 Observable 中(通过Rx.Observable.create())并作为流进一步处理。Oboe.js 事件也可以转换为 Observables(通过Rx.Observable.fromEvent().

  • @IgorVeloso 流式传输时,您必须注意中间的网络部分,例如负载平衡器和反向代理,它们通常会缓冲消息。您的服务器是否正确地分块传送数据,您可以使用 `curl -N localhost:8080/my/endpoint` 来验证(响应应该分块打印)。此外,在客户端,在 AJAX 调用中,整个响应在作为响应移交之前被收集。最近的浏览器确实支持`xhr.onprogress`,它允许部分处理响应。 (2认同)