随Akka流发送元数据

随Akka流发送元数据,akka,akka-stream,Akka,Akka Stream,这是我先前的问题: 我已经设法通过Akka流发送压缩和加密文件。现在,我正在寻找将元数据与数据一起传输的方法,主要是文件名和哈希(校验和) 我目前的想法是使用Flow.prepend函数并以这种方式在数据之前插入元数据: 文件名,其大小可能不同,但始终以空字节结尾 固定大小散列(校验和) 资料 然后,在接收端,我必须使用Flow.takeWhile两次——一次读取文件名,第二次读取哈希,然后只读取数据。它看起来不像是一个优雅的解决方案,而且如果将来我想添加更多的元数据,它会变得更糟 我注意到方法

这是我先前的问题:

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

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

  • 文件名,其大小可能不同,但始终以空字节结尾

  • 固定大小散列(校验和)

  • 资料

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

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

    Add a ``name`` attribute to this Flow.
    
    我不知道如何使用它(如果可以通过它传输文件名)

    问题是:有没有比上面更好的方法通过Akka流传输元数据和数据


    编辑:用idea附加我的绘图。

    我认为预先添加元数据是有意义的。一种简单的方法可以是使用与发送数据相同的帧来预先处理元数据

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

    // 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读取的原始字节流中提取元数据。

    我猜不可能通过使用我自己的对象测试流来预处理元数据,这将包含元数据?如果您要通过TCP流,在接收端,您总是会发现自己有一个原始字节流(即,如果使用Akka流,则通过TestRing)Hmmm。。。这个如何:我将元数据保存在自己的类/对象中,然后将其序列化为json(到字符串),然后使用base64(因此没有空字节)编码,并使用此base64加上空作为分隔符预结束数据?@spam注意,
    Framing.delimiter
    还支持长度字段,因此,您可以在每条数据之前预先设置长度。我个人更喜欢这种方法,因为它更可靠。但我不想在整个流中使用Framing.delimeter-我只想从一开始就使用元数据。