Finagle 快速启动客户端

Finagle quickstart client

我有一个裸 sbt 项目,我已经添加了 "com.twitter" %% "finagle-http" % "6.33.0"。我正在关注 Twitter Finagle 的 quickstart 指南。我的代码是直接复制粘贴:

import com.twitter.finagle.{Http, Service}
import com.twitter.finagle.http
import com.twitter.util.{Await, Future}

object Client extends App {
  val client: Service[http.Request, http.Response] = Http.newService("www.scala-lang.org:80")
  val request = http.Request(http.Method.Get, "/")
  request.host = "www.scala-lang.org"
  val response: Future[http.Response] = client(request)
  response.onSuccess { resp: http.Response =>
    println("GET success: " + resp) 
    println(resp.contentString)    // modification 1
  }
  Await.ready(response)
  println("needed this")           // modification 2
}

没有“modification 2”我根本没有输出。添加 println 后,我得到

needed this
GET success: Response("HTTP/1.1 Status(200)")

Process finished with exit code 0
  1. 为什么不打印没有“modification 2”的响应?
  2. 为什么“modification 1”没有打印出 contentString

如果我在“modification 1”上设置断点,并使用当前状态评估 resp.contentString,则会根据需要返回网站的 HTML。

当程序 运行 正常运行时,我如何打印它?

Twitter FutureonSuccess 方法的签名与标准库 Future 上的方法不同——而不是这个:

def onSuccess[U](pf: PartialFunction[T, U])(implicit executor: ExecutionContext): Unit

你有这个:

def onSuccess(f: (A) ⇒ Unit): Future[A]

即它 return 是一个新的 future,它 return 与旧的 future 具有相同的值,但也执行副作用,而不仅仅是执行副作用。 (作为旁注,在我看来,这是 Twitter 未来 API 优于标准库的众多方式之一——我更喜欢函数参数的 return 类型是 Unit 并且该方法不是)。

你的情况是 Finagle 用于客户端的线程是守护进程,所以如果你不显式地等待未来的结果,就不能保证 JVM 不会在那个未来之前退出很满意。更改您的代码以等待 onSuccess 编辑的未来 return 的结果将使一切按预期工作。