所在的位置: js >> js发展 >> 什么是流式输出

什么是流式输出

北京治青春痘的医院 http://m.39.net/pf/a_8736814.html

阿里妹导读:流式输出在阿里内部已经遍地开花,大家耳熟能详却又好奇不已。清楚的是知道它是性能利器从而提升业务转化,不清楚的是到底什么样的技术才算是流式输出?支撑流式输出的技术理论又有哪些?流式输出适合什么样的应用场景?今天我们就来揭开这层面纱,让大家雾里看花但又能清清楚楚地看到“花”。

一名词理解

1流式

流式(Stream)亦称响应式,是一种基于异步数据流研发框架,是一种概念和编程模型,并非一种技术架构,目前在各技术栈都有响应式的技术框架,前端的React.js、RxJs,服务端以RxJava、Reactor,Android端的RXJava。由此而来的即是响应式编程。

2反应式/响应式编程

反应式编程/响应式编程(ReactiveProgramming)是一种基于事件模型编程范式,众所周知异步编程模式中通常有两种获得上一个任务执行结果的方式,一个就是主动轮训,我们把它称为Proactive方式。另一个就是被动接收反馈,我们称为Reactive。简单来说,在Reactive方式中,上一个任务的结果的反馈就是一个事件,这个事件的到来将会触发下一个任务的执行。

这也就是Reactive的内涵。我们把处理和发出事件的主体称为Reactor,它可以接收事件并处理,也可以在处理完事件后,发出下一个事件给其他Reactor。

下面是一个Reactive模型的示意图:

当然一种新的编码模式,它的RunTime会减少上下文切流从而提升性能,减少内存消耗,与之相反带来的是代码的可维护性降低。衡量优劣需要根据场景带来的收益来衡量。

3流式输出

流式输出就比较神奇,源自于团队内部在一次性能大赛结束后的总结中产生,是基于流式的理论基础在页面渲染以及渲染的HTML在网络传输中的具体应用而诞生,也有人也简单的称之为流式渲染。即:将页面拆分成独立的几部分模块,每个模块有单独的数据源和单独的页面模板,在server端流式的操作每个模块进行业务逻辑处理和页面模板的渲染,然后流式的将渲染出来的HTML输出到网络中,接着分块的HTML数据在网络中传输,接着流式的分块的HTML在浏览器逐个渲染展示。具体流程如下:

针对HTML可以如上所述进行流式输出,衍生出针对json数据的流式输出,其实也是如出一辙,无非少了一层渲染的逻辑,数据流式输出流程跟上图类似,不再赘述。这里可以把客户端的请求当做响应式的一个事件,所以总结就是客户端主动发出请求,服务端流式返回数据,即流式输出。

4端到端响应式

基于流式输出,我们再深入一点,可以发现其实不只是用户端和webserver之间的数据可以在网络上进行流式输出,微服务的各个server之间的数据其实也可以在网络上进行流式输出,如下图所示:

数据可以在网络之间的流式传输,再进一步来看,数据在整条请求响应链路上的流式传输会是什么样子,见下图所示:

综上所述我们定义:端到端响应式=流式输出+响应式编程。

二流式输出理论基础

是什么基础技术理论,支撑我们能够像上述流程那样对数据进行流式输出和接收,下面有几个核心的技术点:

1HTTP分块传输协议

分块传输编码(Chunkedtransferencoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由网页服务器发送给客户端应用(通常是网页浏览器)的数据可以分成多个部分。分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。

如果需要使用分块传输编码的响应格式,我们需要在HTTP响应中设置响应头Transfer-Encoding:chunked。它的具体传输格式是这样的(注意HTTP响应中换行符是\r\n):

HTTP/1.OK\r\n\r\nTransfer-Encoding:chunked\r\n...\r\n\r\nchunked1length\r\nchunked1content\r\nchunked2length\r\nchunked2content\r\n...\r\n0\r\n\r\n\r\n

具体流程见流式输出名词理解部分,分块传输编码例子:

funchandleChunkedHttpResp(connnet.Conn){buffer:=make([]byte,)n,err:=conn.Read(buffer)iferr!=nil{log.Fatalln(err)}fmt.Println(n,string(buffer))conn.Write([]byte(HTTP/1.OK\r\n))conn.Write([]byte(Transfer-Encoding:chunked\r\n))conn.Write([]byte(\r\n))conn.Write([]byte(6\r\n))conn.Write([]byte(hello,\r\n))conn.Write([]byte(8\r\n))conn.Write([]byte(chunked!\r\n))conn.Write([]byte(0\r\n))conn.Write([]byte(\r\n))}

这里需要注意的是HTTP分块传输对同步HTML输出比较适合(对于浏览器来讲),因为在很多web页面涉及SEO,SEO的TDK元素必须同步输出,所以这种方式比较适合,针对于JSON数据的流式输出通过SSE来实现,具体如下。

2HTTPSSE协议

sse(ServerSendEvents)是HTTP的标准协议,是服务端向客户端发送事件流式的方式。在客户端中为一些事件类型绑定监听函数,从而做业务逻辑处理。这里要注意的是SEE是单向的,只能服务器向客户端发送事件流,具体流程如下:

SSE协议中约束了下面几个字段类型

1)event

事件类型。如果指定了该字段,则在客户端接收到该条消息时,会在当前的EventSource对象上触发一个事件,事件类型就是该字段的字段值,你可以使用addEventListener()方法在当前EventSource对象上监听任意类型的命名事件,如果该条消息没有event字段,则会触发onmessage属性上的事件处理函数。

2)data

消息的数据字段。如果该条消息包含多个data字段,则客户端会用换行符把它们连接成一个字符串来作为字段值。

3)id

事件ID,会成为当前EventSource对象的内部属性最后一个事件ID的属性值。

4)retry

一个整数值,指定了重新连接的时间(单位为毫秒),如果该字段值不是整数,则会被忽略。

客户端代码示例

//客户端初始化事件源constevtSource=newEventSource(//api.example.


转载请注明:http://www.aierlanlan.com/tzrz/5266.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了