Akka流Source.repeat在100个请求后停止

时间:2019-01-08 01:23:10

标签: scala akka akka-stream akka-http

我正在使用下面的流处理系统来从一个来源抓取帧,进行处理,然后发送到另一个。我通过他们的scapa API使用了akka-streamsakka-http的组合。管道非常短,但我似乎无法找到系统在精确地向端点发出100个请求后决定停止的位置。

object frameProcessor extends App {
  implicit val system: ActorSystem = ActorSystem("VideoStreamProcessor")
  val decider: Supervision.Decider = _ => Supervision.Restart
  implicit val materializer: ActorMaterializer = ActorMaterializer()
  implicit val dispatcher: ExecutionContextExecutor = system.dispatcher
  val http = Http(system)
  val sourceConnectionFlow: Flow[HttpRequest, HttpResponse, Future[Http.OutgoingConnection]] = http.outgoingConnection(sourceUri)

  val byteFlow: Flow[HttpResponse, Future[ByteString], NotUsed] =
    Flow[HttpResponse].map(_.entity.dataBytes.runFold(ByteString.empty)(_ ++ _))

  Source.repeat(HttpRequest(uri = sourceUri))
    .via(sourceConnectionFlow)
    .via(byteFlow)
    .map(postFrame)
    .runWith(Sink.ignore)
    .onComplete(_ => system.terminate())

  def postFrame(imageBytes: Future[ByteString]): Unit = {
    imageBytes.onComplete{
      case Success(res) => system.log.info(s"post frame. ${res.length} bytes")
      case Failure(_) => system.log.error("failed to post image!")
    }
  }
}

参考,我正在使用akka-streams版本 2.5.19 akka-http版本 10.1.7 。不会引发任何错误,在框架来自的源服务器上也没有错误代码,并且程序以错误代码0退出。

我的application.conf如下:

logging = "DEBUG"

始终处理100个单位。

谢谢!

编辑

像这样将记录添加到流中

.onComplete{
  case Success(res) => {
    system.log.info(res.toString)
    system.terminate()
  }
  case Failure(res) => {
    system.log.error(res.getMessage)
    system.terminate()
  }

}

收到一个连接重置异常,但这是不一致的。流以Done完成。

编辑2

使用.mapAsync(1)(postFrame),恰好在100个请求后,我得到了相同的Success(Done)。另外,当我检查nginx服务器access.logerror.log时,只有200个响应。

我必须按如下方式修改postFrame才能运行mapAsync

def postFrame(imageBytes: Future[ByteString]): Future[Unit] = {
  imageBytes.onComplete{
    case Success(res) => system.log.info(s"post frame. ${res.length} bytes")
    case Failure(_) => system.log.error("failed to post image!")
  }
  Future(Unit)
}

1 个答案:

答案 0 :(得分:2)

我相信我已经在Akka docs using delayed restarts with a backoff operator上找到了答案。我使用{ message: "John Doe" owner: { name: "John Doe", initials: "JD" } } RestartSource.withBackoff代替从不稳定的远程连接直接采购。修改后的流看起来像;

RestartSource.onFailureWithBackoff

我无法找到问题的根源,但似乎可以解决问题。