合成流的目的是什么(来自Sink和Source)?

时间:2019-04-13 20:28:29

标签: akka akka-stream

我正在尝试从website了解理解的复合流(来自Sink和Source),它们表示如下:

enter image description here

有人可以提供使用复合流的示例。
我什么时候应该使用它?

3 个答案:

答案 0 :(得分:1)

也许在某些情况下,您只需要提供流程,在某些情况下,您需要NoOp流程。 那你可以做

Flow.fromSinkAndSource(Sink.ignore,Source.empty)

或者忽略来源中的每个元素,而使用另一个元素

Flow.fromSinkAndSource(Sink.ignore,Source.tick(1.second,1.second,"something"))

答案 1 :(得分:1)

Flow.fromSinkAndSource提供了一种方便的方式来组装flow,其中sink作为输入,而source作为未连接,这可能是最好的如下图所示(可在API链接中找到):

  +----------------------------------------------+
  | Resulting Flow[I, O, NotUsed]                |
  |                                              |
  |  +---------+                  +-----------+  |
  |  |         |                  |           |  |
I ~~>| Sink[I] | [no-connection!] | Source[O] | ~~> O
  |  |         |                  |           |  |
  |  +---------+                  +-----------+  |
  +----------------------------------------------+

如@gabrielgiussi的答案所示,它通常用于以下情况:要将现有source(或flow)的输出“切换”到某些不同的输出-用于测试或其他目的-不。这是一个简单的示例:

import akka.actor.ActorSystem
import akka.stream.scaladsl._
implicit val system = ActorSystem("system")
implicit val materializer = ActorMaterializer()

val switchFlow = Flow.fromSinkAndSource( Sink.ignore, Source(List("a", "b", "c")) )

Source(1 to 5).via(switchFlow).runForeach(println)
// res1: scala.concurrent.Future[akka.Done] = Future(Success(Done))
// a
// b
// c

还值得注意的是,该方法的“垫”版本fromSinkAndSourceMat具有一些有趣的用例。一个示例是使用它来使half-closed WebSockets保持打开状态,方法是使用Source.maybe[T]来维护Promise[Option[T]]作为物化值,当一个人想要关闭连接时将完成该值。以下是Akka-http WebSockets client support文档中相关部分的示例代码:

// using Source.maybe materializes into a promise
// which will allow us to complete the source later
val flow: Flow[Message, Message, Promise[Option[Message]]] =
  Flow.fromSinkAndSourceMat(
    Sink.foreach[Message](println),
    Source.maybe[Message])(Keep.right)

val (upgradeResponse, promise) =
  Http().singleWebSocketRequest(
    WebSocketRequest("ws://example.com:8080/some/path"),
    flow)

// at some later time we want to disconnect
promise.success(None)

答案 2 :(得分:0)

我从here那里得到了理解

object SingleWebSocketRequest {
    def main(args: Array[String]) = {     

    // print each incoming strict text message
    val printSink: Sink[Message, Future[Done]] =
      Sink.foreach {
        case message: TextMessage.Strict =>
          println(message.text)
      }
 
    val helloSource: Source[Message, NotUsed] =
      Source.single(TextMessage("hello world!"))
 
    // the Future[Done] is the materialized value of Sink.foreach
    // and it is completed when the stream completes
    val flow: Flow[Message, Message, Future[Done]] =
      Flow.fromSinkAndSourceMat(printSink, helloSource)(Keep.left)
 
    // upgradeResponse is a Future[WebSocketUpgradeResponse] that
    // completes or fails when the connection succeeds or fails
    // and closed is a Future[Done] representing the stream completion from above
    val (upgradeResponse, closed) =
      Http().singleWebSocketRequest(WebSocketRequest("ws://echo.websocket.org"), flow)
 
    val connected = upgradeResponse.map { upgrade =>
      // just like a regular http request we can access response status which is available via upgrade.response.status
      // status code 101 (Switching Protocols) indicates that server support WebSockets
      if (upgrade.response.status == StatusCodes.SwitchingProtocols) {
        Done
      } else {
        throw new RuntimeException(s"Connection failed: ${upgrade.response.status}")
      }
    }
 
    // in a real application you would not side effect here
    // and handle errors more carefully
    connected.onComplete(println)
    closed.foreach(_ => println("closed"))
    }
    }