我写了一个小样本程序(包括在下面),演示了我与Akka的问题。如果我试图在Akka尝试将连接升级到WebSocket的阶段之前尝试连接的服务器出现问题,这对代码是如何可见的?当我运行这个例子时,我可以看到一个调试语句,表明连接被拒绝但Future没有返回,最终Await.result会超时。
import akka.Done
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.ws.{Message, TextMessage, WebSocketRequest, WebSocketUpgradeResponse}
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Flow, Keep, Sink, Source}
import com.typesafe.config.ConfigFactory
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import scala.util.control.NonFatal
object WebSocketClientProblem {
def main(args: Array[String]) : Unit = {
try {
implicit val sys = ActorSystem("websocket",ConfigFactory.parseString("akka.loglevel = \"DEBUG\""))
implicit val mat = ActorMaterializer()
import sys.dispatcher
val incoming = Sink.foreach[Message](m => println(m))
val outgoing = Source.single(TextMessage.Strict("Hello"))
val flow: Flow[Message, Message, Future[WebSocketUpgradeResponse]] = Http().webSocketClientFlow(WebSocketRequest("ws://localhost:8081/echo"))
val upgradeResponse = outgoing
.viaMat(flow)(Keep.right)
.toMat(incoming)(Keep.left)
.run()
val connected: Future[Done.type] = upgradeResponse.flatMap { upgrade =>
if(upgrade.response.status == StatusCodes.OK || upgrade.response.status == StatusCodes.SwitchingProtocols) {
Future.successful(Done)
} else {
println("switch to websocket was not successful")
throw new RuntimeException(s"Connection failed: ${upgrade.response}")
}
}
// When the server is not listening how does the Connection Refused error get made visible to the code?
val r = Await.result(connected, 30 seconds)
println(s"Result was [$r]")
} catch {
case NonFatal(e) =>
println(s"Caught ${e.getMessage}")
}
}
}