我想禁止使用varnish的URL。我首先要做的是从领事那里收集所有健康的知识产权。
private def nodeInfo:Future[List[NodeInfo]] = {
val request = HttpRequest(method = HttpMethods.GET, uri = consulUrl)
Future.successful {
Http().singleRequest(request).flatMap(response =>
response.status match {
case OK => Unmarshal(response).to[List[NodeInfo]]
case _ =>
response.entity.toStrict(5.seconds).flatMap { entity =>
val body = entity.data.decodeString("UTF-8")
log.warning(errorMessage(request, response, body))
Future.failed(new IOException(errorMessage(response, body)))
}
})
}.flatMap(value => value)
}
这可以按预期工作。 在理解的帮助下,我想遍历所有这些。
def banFromCache(toBanUrl:String): Future[String] = {
for {
nodes <- nodeInfo
result <- loopNodes(nodes, toBanUrl)
} yield result
}
使用foreach循环,我发送HttpRequest并获取每个HttpResponses。但由Future函数引起的结果是在请求完成之前完成。
private def loopNodes(nodes:List[NodeInfo], toBanUrl:String):Future[String] = Future {
val banResult = new ListBuffer[String]
nodes.foreach(node => {
banAllHealthy(node, toBanUrl).onComplete {
case Failure(err) =>
banResult += node.Node.Address + " " + err.getMessage
log.error("Request failed: " + node.Node.Address + " " + err.getMessage)
case Success(res) =>
banResult += node.Node.Address + " " + res.toString
log.info("Request success: " + node.Node.Address + " " + res.toString)
}
})
banResult.toList.toString()
}
private def banAllHealthy(nodeInfo:NodeInfo, toBanUrl: String):Future[HttpResponse] = {
def request(): Future[HttpResponse] =
Http().singleRequest(HttpRequest(method = HttpMethods.GET, uri = "http://localhost:9000/healthcheck"))
//Http().singleRequest(HttpRequest(method = HttpMethods.GET, uri = "http://" + nodeInfo.Node.Address + "/" + toBanUrl))
val responseFuture: Future[HttpResponse] = request()
responseFuture
}
这里的路线非常简单:
} ~ pathPrefix("ban") {
pathPrefix(Segment) { banpath =>
pathEndOrSingleSlash {
get {
complete(banFromCache(banpath).map(_.asJson))
}
}
}
有没有办法一次显示所有回复?
答案 0 :(得分:1)
要累积结果字符串,请保持在Future
:
private def loopNodes(nodes: List[NodeInfo], toBanUrl: String): Future[String] = {
val futures: List[Future[String]] = nodes.map { node =>
banAllHealthy(node, toBanUrl)
.map(res => s"${node.Node.Address} ${res}")
.recover { case err => s"${node.Node.Address} ${err.getMessage}" }
}
Future.reduceLeft(futures)(_ + "\n" + _)
}
答案 1 :(得分:0)
如果你把回调放在处理每个未来的结果上,你将失去对执行的控制。随着foreach,每个未来都生活在自己的并行执行中。父母未来的收益是因为它不会等待任何事情。我建议不要使用ListBuffer并使用更不可变的样式。无论如何,尝试将整个计算构建为封装整个计算的一个未来:
private def loopNodes(nodes:List[NodeInfo], toBanUrl:String):Future[String] = {
nodes.map { node =>
// Creates a tuple to store current node and http result
// (Node, result, HttpResult)
(node, "", banAllHealthy(node, toBanUrl))
}.foldLeft(Future(""))((str, b) =>
b match {
case (node, str ,response) => {
// Each response will be transformed to string
(response map (result => str + " " + node.Node.Address + " " + "Success"))
// In case of node is not available its suppose that the HttpClient will raise an execption
.recover {
case err: Throwable =>
str + " " + node.Node.Address + " " + "Error " + err.getMessage
case _ =>
str + " " + node.Node.Address + " " + "Unknown Error"
}
}
})
}