我有akka-http
提供的Rest API。在某些情况下,我需要从外部数据库(Apache HBase
)获取数据,如果数据库花费太长时间来传递数据,我希望查询失败。
一种天真的方法是将呼叫包裹在Future
内,然后使用Await.result
将其阻止,并持有所需的持续时间。
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
object AsyncTest1 extends App {
val future = Future {
getMyDataFromDB()
}
val myData = Await.result(future, 100.millis)
}
由于此实现需要两个线程,因此似乎效率低下。有一种有效的方法吗?
我有另一个用例,我希望并行发送多个查询,然后聚合结果,并具有相同的延迟限制。
val future1 = Future {
getMyDataFromDB1()
}
val future2 = Future {
getMyDataFromDB2()
}
val foldedFuture = Future.fold(
Seq(future1, future2))(MyAggregatedData)(myAggregateFunction)
)
val myData = Await.result(foldedFuture, 100.millis)
同样的问题,实现这个的最有效方法是什么?
感谢您的帮助
答案 0 :(得分:3)
一种解决方案是使用Akka的after
函数,它可以让你传递一个持续时间,之后将会抛出一个异常或任何你想要的东西。
看看here。它演示了如何实现这一点。
编辑: 我想我会在这里发布代码,以防链接在将来被破坏:
import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
import akka.actor.ActorSystem
import akka.pattern.after
val system = ActorSystem("theSystem")
lazy val f = future { Thread.sleep(2000); true }
lazy val t = after(duration = 1 second, using = system.scheduler)(Future.failed(new TimeoutException("Future timed out!")))
val fWithTimeout = Future firstCompletedOf Seq(f, t)
fWithTimeout.onComplete {
case Success(x) => println(x)
case Failure(error) => println(error)
}