使用Akka Stream从DataBase流式传输记录

时间:2017-07-09 18:22:33

标签: akka akka-stream reactive-streams

我有一个使用Akka的系统,它目前通过消息队列处理传入的流数据。当记录到达时,它会被处理,mq被激活并传递记录以便在系统内进一步处理。

现在我想添加对使用DB作为输入的支持 什么是输入源能够处理数据库的方法(应该以接收器可以处理的速度输入> 100M记录 - 所以我假设反应/ akka-streams?)?

2 个答案:

答案 0 :(得分:7)

光滑图书馆

Slick streaming通常是这样做的。

稍微扩展光滑的文档以包含akka流:

//SELECT Name from Coffees
val q = for (c <- coffees) yield c.name

val action = q.result

type Name = String

val databasePublisher : DatabasePublisher[Name] = db stream action

import akka.stream.scaladsl.Source

val akkaSourceFromSlick : Source[Name, _] = Source fromPublisher databasePublisher

现在akkaSourceFromSlick就像任何其他akka流Source一样。

&#34; Old School&#34;结果集

也可以使用普通ResultSet,而不是光滑的&#34;引擎&#34;对于akka流。我们将利用可以从Source实例化流Iterator的事实。

首先使用标准的jdbc技术创建ResultSet:

import java.sql._

val resultSetGenerator : () => Try[ResultSet] = Try {
  val statement : Statement = ???
  statement executeQuery "SELECT Name from Coffees"
}

当然,所有ResultSet实例都必须在第一行之前移动光标:

val adjustResultSetBeforeFirst : (ResultSet) => Try[ResultSet] = 
  (resultSet) => Try(resultSet.beforeFirst()) map (_ => resultSet)

一旦我们开始遍历行,我们就必须从正确的列中提取值:

val getNameFromResultSet : ResultSet => Name = _ getString "Name"

现在我们可以实现Iterator接口从ResultSet创建Iterator[Name]

val convertResultSetToNameIterator : ResultSet => Iterator[Name] = 
  (resultSet) => new Iterator[Try[Name]] {
    override def hasNext : Boolean  = resultSet.next
    override def next() : Try[Name] = Try(getNameFromResultSet(resultSet))
   } flatMap (_.toOption)

最后,将所有部分粘合在一起以创建我们需要传递给Source.fromIterator的功能:

val resultSetGenToNameIterator : (() => Try[ResultSet]) => () => Iterator[Name] = 
  (_ : () => Try[ResultSet])
    .andThen(_ flatMap adjustResultSetBeforeFirst) 
    .andThen(_ map convertResultSetToNameIterator) 
    .andThen(_ getOrElse Iterator.empty)

此迭代器现在可以提供源:

val akkaSourceFromResultSet : Source[Name, _] = 
  Source fromIterator resultSetGenToNameIterator(resultSetGenerator)

此实现一直反应到数据库。由于ResultSet一次预取有限数量的行,因此数据将仅通过数据库从硬盘驱动器中流出,因为流Sink发出信号需求。

答案 1 :(得分:0)

与Java Publisher界面相比,我发现Alpakka文档非常出色,并且是使用响应流的一种更轻松的方法。

Alpakka项目是一个开源计划,旨在为Java和Scala实现流感知的,反应性的集成管道。它建立在Akka Streams之上,并且是从头开始设计的,旨在原生地理解流,并为反应式和面向流的编程提供DSL,并内置对反压的支持

带有Slick的Alpakka文档:https://doc.akka.io/docs/alpakka/current/slick.html

Alpakka Github:https://github.com/akka/alpakka