端到端响应式流 RESTful 服务 [英] End-to-End Reactive Streaming RESTful service

查看:38
本文介绍了端到端响应式流 RESTful 服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已阅读这篇文章 我不知道这是不是一个愚蠢的问题.我是响应式编程的新手.

I have read this post and I don't know if it is a stupid question. I am completely newbie in reactive programming.

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

The question is very simple: supposing I have a fully-reactive back-end, how can I stream to browser (a large text, for instance), and print each chunk to the user as soon as they come from server?

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

Probably I am missing some important conceptual points, but all I need to know is: Can I send small parts of data (from server to browser), with one single HTTP GET (? or not) request? The key is: can I write those small parts, until the whole data is sent?

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

Thanks for any help. I really tried google before, but I always get information about other concepts (like websockets, long-polling, react.js), that I think it is not the case.

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

I'am not asking for a specific API ou library. I just want to understand the concept, for example: "You CANNOT do this with HTTP protocol, period!" or "This has NOTHING to do with Reactive Programming, you are confused about what stream really means. See 'something_else.js' ".

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

I did a small rest controller using spring-mvc (spring-boot) with this method:

@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();
    }

}

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

In the browser, only the whole response arrived, even using the flushBuffer. After some research, that this could be a TOMCAT issue, I changed my pom.xml including undertow:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

使用默认配置:

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

此时,在我的 IDE 中使用 debug,每个块都在flushBuffer 之后写入.

At this moment, using debug in my IDE, each chunk was being written after the flushBuffer.

所以,我相信这可能是一个 TOMCAT 配置.长话短说,我知道在流媒体解决方案"方面有很多东西可以帮助我,感谢所有评论,但我的问题有点概念化.

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.

推荐答案

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

There is a protocol on top of HTTP which allows delivery of a server response in smaller, ready-to-be-consumed, chunks to the browser using HTTP transport. It's called SSE (Server Sent Events) or EventSource, here is pretty thoroughly assembled article on the topic.

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

There are other means to stream data using the HTTP protocol. One such alternative is JSON streaming, in which you write partial responses on the wire from the server and consume the JSON chunks when they arrive. On the consuming side a popular library is called Oboe.js, on the server side you basically need to write the partial data on the response wire when you want to sent it, or when it's available.

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

For both approaches Rx is useful for handling the streaming logic on the server side. You model the pieces as a stream (handle errors, etc.) and eventually, in the Subscriber, you write the single emissions on the wire, closing the response when the Observable is finished.

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

On the client side, the EventSource events can be wrapped in a new Observable (via Rx.Observable.create()) and processed further as a stream. Also Oboe.js events can be converted into Observables (via Rx.Observable.fromEvent().

这篇关于端到端响应式流 RESTful 服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆