Akka http 丢失发件人参考
Akka http losing sender reference
收到 Future[httpResponse]
后,我试图将消息发送到 sender
,但我丢失了 sender
的引用。
这是我的接收方法的代码:
def receive = {
case Seq(method: HttpMethod, endpoint: String, payload: String) ⇒ {
// I have the correct sender reference
implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(context.system)) // needed by singleRequest method below
// I have the correct sender reference
val response: Future[HttpResponse] = Http(context.system).singleRequest(HttpRequest(method = method, uri = endpoint, entity = payload))
println("http request sent")
// I have the correct sender reference
response onSuccess {
case HttpResponse(statusCode, _, entity, _) ⇒ {
entity.dataBytes.runFold(ByteString.empty)(_ ++ _).foreach { body ⇒
// NO Reference to sender
sender ! HttpConsumerResponse(statusCode = statusCode, contentType = entity.contentType, body = body.utf8String)
}
}
case _ => println("http request success 2")
}
response onFailure {
case exception: Throwable ⇒ {
println("http request failure")
throw exception
} // Adopting let-it-crash fashion by re-throwning the exception
}
}
case _ => println("I am httpConsumerActor and I don't know")
}
如果我这样更改代码:
def receive = {
case Seq(method: HttpMethod, endpoint: String, payload: String) ⇒ {
// I have the correct sender reference
implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(context.system)) // needed by singleRequest method below
// I have the correct sender reference
val response: Future[HttpResponse] = Http(context.system).singleRequest(HttpRequest(method = method, uri = endpoint, entity = payload))
println("http request sent")
// I have the correct sender reference
val mySender = sender
response onSuccess {
case HttpResponse(statusCode, _, entity, _) ⇒ {
entity.dataBytes.runFold(ByteString.empty)(_ ++ _).foreach { body ⇒
// NO Reference to sender
mySender ! HttpConsumerResponse(statusCode = statusCode, contentType = entity.contentType, body = body.utf8String)
}
}
case _ => println("http request success 2")
}
response onFailure {
case exception: Throwable ⇒ {
println("http request failure")
throw exception
} // Adopting let-it-crash fashion by re-throwning the exception
}
}
case _ => println("I am httpConsumerActor and I don't know")
}
一切正常,但我必须像这条线一样发送演员的参考,我知道这不是最好的方法:
val mySender = sender
你的拳头方法不起作用的原因是你是"closing over mutable state",即sender()
方法是在执行onComplete时执行的,并且不再包含引用。这是 Akka 中一个相当常见的错误,我们都曾遇到过! :)
正如您自己发现的那样,正确的解决方案是预存储引用。还有其他选项,例如 "becoming" 其他选项,但为了您的使用,我会说预存储是 "nice" 和 "simple" 之间权衡的正确方法。
参考这些资源:, Blog post
收到 Future[httpResponse]
后,我试图将消息发送到 sender
,但我丢失了 sender
的引用。
这是我的接收方法的代码:
def receive = {
case Seq(method: HttpMethod, endpoint: String, payload: String) ⇒ {
// I have the correct sender reference
implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(context.system)) // needed by singleRequest method below
// I have the correct sender reference
val response: Future[HttpResponse] = Http(context.system).singleRequest(HttpRequest(method = method, uri = endpoint, entity = payload))
println("http request sent")
// I have the correct sender reference
response onSuccess {
case HttpResponse(statusCode, _, entity, _) ⇒ {
entity.dataBytes.runFold(ByteString.empty)(_ ++ _).foreach { body ⇒
// NO Reference to sender
sender ! HttpConsumerResponse(statusCode = statusCode, contentType = entity.contentType, body = body.utf8String)
}
}
case _ => println("http request success 2")
}
response onFailure {
case exception: Throwable ⇒ {
println("http request failure")
throw exception
} // Adopting let-it-crash fashion by re-throwning the exception
}
}
case _ => println("I am httpConsumerActor and I don't know")
}
如果我这样更改代码:
def receive = {
case Seq(method: HttpMethod, endpoint: String, payload: String) ⇒ {
// I have the correct sender reference
implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(context.system)) // needed by singleRequest method below
// I have the correct sender reference
val response: Future[HttpResponse] = Http(context.system).singleRequest(HttpRequest(method = method, uri = endpoint, entity = payload))
println("http request sent")
// I have the correct sender reference
val mySender = sender
response onSuccess {
case HttpResponse(statusCode, _, entity, _) ⇒ {
entity.dataBytes.runFold(ByteString.empty)(_ ++ _).foreach { body ⇒
// NO Reference to sender
mySender ! HttpConsumerResponse(statusCode = statusCode, contentType = entity.contentType, body = body.utf8String)
}
}
case _ => println("http request success 2")
}
response onFailure {
case exception: Throwable ⇒ {
println("http request failure")
throw exception
} // Adopting let-it-crash fashion by re-throwning the exception
}
}
case _ => println("I am httpConsumerActor and I don't know")
}
一切正常,但我必须像这条线一样发送演员的参考,我知道这不是最好的方法:
val mySender = sender
你的拳头方法不起作用的原因是你是"closing over mutable state",即sender()
方法是在执行onComplete时执行的,并且不再包含引用。这是 Akka 中一个相当常见的错误,我们都曾遇到过! :)
正如您自己发现的那样,正确的解决方案是预存储引用。还有其他选项,例如 "becoming" 其他选项,但为了您的使用,我会说预存储是 "nice" 和 "simple" 之间权衡的正确方法。
参考这些资源: