我正在使用下面的流处理系统来从一个来源抓取帧,进行处理,然后发送到另一个。我通过他们的scapa API使用了akka-streams
和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
版本 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
完成。
使用.mapAsync(1)(postFrame)
,恰好在100个请求后,我得到了相同的Success(Done)
。另外,当我检查nginx服务器access.log
和error.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)
}
答案 0 :(得分:2)
我相信我已经在Akka docs using delayed restarts with a backoff operator上找到了答案。我使用{
message: "John Doe"
owner: {
name: "John Doe",
initials: "JD"
}
}
和不 RestartSource.withBackoff
代替从不稳定的远程连接直接采购。修改后的流看起来像;
RestartSource.onFailureWithBackoff
我无法找到问题的根源,但似乎可以解决问题。