想搞下Akka HTTP,用于用于我们的开源项目football,发现Akka HTTP的例子里大量用到Akka Stream,而且Akka HTTP是构建Akka Stream之上的。
所以还是先看下Akka Stream吧,先了解下这个Akka Stream这个项目的动机。
动机
Motivation
The way we consume services from the internet today includes many instances of streaming data, both down- loading from a service as well as uploading to it or peer-to-peer data transfers. Regarding data as a stream of elements instead of in its entirety is very useful because it matches the way computers send and receive them (for example via TCP), but it is often also a necessity because data sets frequently become too large to be handled as a whole. We spread computations or analyses over large clusters and call it “big data”, where the whole principle of processing them is by feeding those data sequentially—as a stream—through some CPUs.
现如今我们从因特网上获取服务的方式包括了很多流式的数据,比如下载、上传或是p2p(peer to peer)的数据传输。把数据视为元素(译注:即整体的组成部分)的流而不是整体可以更有用,因为它符合计算机实际上处理它的方式(例如,通过TCP),但是经常这也是必需的,因为数据集经常变得太大而不能当作整体处理。我们把计算和分析分布到一个大集群中,称之为“大数据”,它的处理原则就是把数据顺序地(作为流)提供给一些CPU
Actors can be seen as dealing with streams as well: they send and receive series of messages in order to transfer knowledge (or data) from one place to another. We have found it tedious and error-prone to implement all the proper measures in order to achieve stable streaming between actors, since in addition to sending and receiving we also need to take care to not overflow any buffers or mailboxes in the process. Another pitfall is that Actor messages can be lost and must be retransmitted in that case lest the stream have holes on the receiving side. When dealing with streams of elements of a fixed given type, Actors also do not currently offer good static guarantees that no wiring errors are made: type-safety could be improved in this case.
也可以认为actor处理的也是流:它们接收消息、发送消息,来把知识(或者数据)从一个地方传送到另一个地方。我们发现想要使用恰当的实现手段来在actor之间构造一个稳定的流非常繁杂、容易出错,因为在接收和发送之外,我们还得确保不会使得缓冲区和mailbox(actor的mailbox)溢出。另一个陷阱是,Actor的消息可能会丢失,因此需要进行重传,以免在流的接收端出现漏洞。有的流的元素是一个给定的类型,在处理这种情况是,actor并不能提供很好的静态保证(译注:指编译器的类型检查)来确保不变有交织时的错误(译注:应该是指消息流的编织),在这种情况下类型安全可以改进。
(译注:这一段说明了设计Akka Stream的动机:
1. 确保stream经过的各处的缓冲不会溢出(可以认为mailbox是actor的消息缓冲)
2. 保证消息传递的可靠性,提供高于at-least-once的消息传递语义。
3. 在处理元素类型给定的流时,提供类型安全。
这些问题在构造一个actor系统时,是非常核心的问题。特别是前两个,自己构造actor系统时的确得采用很繁琐的手段才能实现。actor系统存在的问题,可以参考下这篇文章
)
For these reasons we decided to bundle up a solution to these problems as an Akka Streams API. The purpose is to offer an intuitive and safe way to formulate stream processing setups such that we can then execute them efficiently and with bounded resource usage—no more OutOfMemoryErrors. In order to achieve this our streams need to be able to limit the buffering that they employ, they need to be able to slow down producers if the consumers cannot keep up. This feature is called back-pressure and is at the core of the Reactive Streams initiative of which Akka is a founding member. For you this means that the hard problem of propagating and reacting to back-pressure has been incorporated in the design of Akka Streams already, so you have one less thing to worry about; it also means that Akka Streams interoperate seamlessly with all other Reactive Streams implementations (where Reactive Streams interfaces define the interoperability SPI while implementations like Akka Streams offer a nice user API).
由于这些原因,我们想要把解决方案打包进Akka Stream API里。目的是提供一个直观和安全的方式来设计流处理过程,使得我们可以高效地执行它们,而且使用有界的资源消耗——不再有OutOfMemoryErrors。为了实现这点,我们的流需要能够限制它们采用的缓冲大小,在消费者跟不上生产者时,我们需要能使用生产者慢下来。这个特性称为后向压力(back-pressure),它是Reactive Streams的核心提议,而Akka是Reactive Streams的创始成员。对你而言这意味着传递和应对back-pressure的问题已经被纳入了Akka Stream的设计,所以你的担心可以少一个了;这也意味着Akka Streams可以无缝地与其它Reactive Streams的实现(Reactive Streams接口定义了互操作的Service Provider Interface,而像Akka这样的实现提供了一个很好地用户API)互操作。
Reactive Streams好像很NB的样子, 在github上已经有五百多个星了。