发送元数据和Akka流

时间:2017-02-25 19:57:52

标签: akka akka-stream

以下是我之前的问题:Send data from InputStream over Akka/Spring stream

我设法通过Akka流发送压缩和加密文件。现在,我正在寻找传输元数据和数据的方法,主要是文件名和哈希(校验和)。

我目前的想法是使用Flow.prepend函数并以这种方式在数据之前插入元数据:

  1. filename,大小可能不同但始终以空字节结尾

  2. 固定大小哈希(校验和)

  3. 数据

  4. 然后,在接收端我将不得不使用Flow.takeWhile两次 - 一次读取文件名,第二次读取哈希,然后只读取数据。它看起来并不像优雅的解决方案,如果将来我想添加更多的元数据,它将变得更糟。

    我注意到方法Flow.named,但是文档只说:

    Add a ``name`` attribute to this Flow.
    

    我不知道如何使用它(如果可以在其上传输文件名)。

    问题是:通过Akka流传输元数据和上传数据是否更好?

    编辑:用想法附上我的绘图。idea

1 个答案:

答案 0 :(得分:1)

我认为预先添加元数据是有道理的。一种简单的方法可以是使用您用来发送数据的相同框架来预先添加元数据。

接收端需要知道有多少元数据块,并使用此信息进行拆分。见下面的例子。

// client end
filenameSrc
  .concat(hashSrc)
  .concat(dataSrc)
  .via(Framing.delimiter(ByteString("\n"), Int.MaxValue, allowTruncation = true))
  .via(Tcp().outgoingConnection(???, ???))
  .runForeach{ ??? }

// server end
val printMetadata =
  Flow.fromGraph(GraphDSL.create() { implicit builder: GraphDSL.Builder[NotUsed] =>
    import GraphDSL.Implicits._

    val metadataSink = Sink.foreach(println)
    val bcast = builder.add(Broadcast[ByteString](2))

    bcast.out(0).take(2) ~> metadataSink

    FlowShape(bcast.in, bcast.out(1).drop(2).outlet)
  })

val handler =
  Framing.delimiter(ByteString("\n"), Int.MaxValue)
  .via(printMetadata)
  .via(???)

这只是解决此问题的众多可行方法之一。但无论您选择何种解决方案,接收方都需要了解如何从通过TCP读取的原始字节流中提取元数据。