Scala Akka streams Source.在100个请求后重复停止

Scala Akka streams Source.在100个请求后重复停止,scala,akka,akka-stream,akka-http,Scala,Akka,Akka Stream,Akka Http,我正在开发流下处理系统,从一个源抓取帧,处理并发送到另一个源。我通过scapaapi使用了akka流和akka http的组合。管道非常短,但我似乎找不到系统在向端点发出100个请求后决定停止的位置 object frameProcessor extends App { implicit val system: ActorSystem = ActorSystem("VideoStreamProcessor") val decider: Supervision.Decider = _ =&

我正在开发流下处理系统,从一个源抓取帧,处理并发送到另一个源。我通过scapaapi使用了
akka流
akka 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
version2.5.19
akka-http
version10.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()
  }

}
收到连接重置异常,但不一致。流在
完成时结束

编辑2 使用
.mapsync(1)(postFrame)
我在100次请求之后获得了相同的
成功(Done)
。此外,当我检查nginx服务器
access.log
error.log
时,只有
200
响应

为了运行
mapsync

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)
}

我相信我已经在网上找到了答案。我使用
RestartSource.withBackoff
not
RestartSource.onFailureWithBackoff
,而不是直接从不稳定的远程连接获取资源。修改后的流看起来像

val restartSource = RestartSource.withBackoff(
  minBackoff = 100.milliseconds,
  maxBackoff = 1.seconds,
  randomFactor = 0.2
){ () =>
  Source.single(HttpRequest(uri = sourceUri))
    .via(sourceConnectionFlow)
    .via(byteFlow)
    .mapAsync(1)(postFrame)
}
restartSource
  .runWith(Sink.ignore)
  .onComplete{
    x => {
      println(x)
      system.terminate()
    }
 } 

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

如果将日志添加到
.onComplete(=>system.terminate())
,会发生什么情况?可能是服务器在100帧后停止发送数据。谢谢提示。看起来连接已由对等主机重置。我认为使用重新启动决策器会导致流重新启动,但事实并非如此。我在哪里可以捕捉到连接重置错误?不是在这个例子中,而是在我的代码中,我使用了一个
RestartSource.onFailureWithBackoff
,它仍然会出错。感谢您的回复运行几次,并不总是存在连接重置错误。相反,我刚刚获得了
成功(完成)
@Andrew如果您使用
mapsync
而不是
map
,会发生什么?我刚刚注意到一件事(可能只是在您的问题代码中,而不是在您的真实代码中),但您的
决策者是否被使用了?我认为应该将其传递给
actormatarializer
构造函数。