Как закрыть клиент Finagle Thrift?
Я использую scrooge + thrift для генерации кода сервера и клиента. Пока все работает отлично.
Вот упрощенный пример того, как я использую свой клиент:
private lazy val client =
Thrift.newIface[MyPingService[Future]](s"$host:$port")
def main(args: Array[String]): Unit = {
logger.info("ping!")
client.ping().foreach { _ =>
logger.info("pong!")
// TODO: close client
sys.exit(0)
}
}
Все работает просто отлично, но сервер жалуется при выходе из программы по поводу незакрытых соединений. Я просмотрел все, но не могу понять, как закрыть client
пример.
Итак, мой вопрос, как вы закрываете комиссионный клиент Finagle? Я чувствую, что упускаю что-то очевидное.
2 ответа
Насколько я знаю, когда вы используете автоматический Thrift.newIface[Iface]
метод для создания вашего сервиса, вы не можете закрыть его, потому что ваш код знает о результирующем значении только то, что он соответствует Iface
, Если вам нужно закрыть его, вы можете создать экземпляр своего клиента в два этапа, создав сервис Thrift в одном и адаптировав его к своему интерфейсу в другом.
Вот как это выглядит, если вы используете Scrooge для создания интерфейса Thrift:
val serviceFactory: ServiceFactory[ThriftClientRequest,Array[Byte]] =
Thrift.newClient(s"$host:$port")
val client: MyPingService[Future] =
new MyPingService.FinagledClient(serviceFactory.toService)
doStuff(client).ensure(serviceFactory.close())
Я попробовал это в репле, и у меня это сработало. Вот слегка отредактированная стенограмма:
scala> val serviceFactory = Thrift.newClient(...)
serviceFactory: ServiceFactory[ThriftClientRequest,Array[Byte]] = <function1>
scala> val tweetService = new TweetService.FinagledClient(serviceFactory.toService)
tweetService: TweetService.FinagledClient = TweetService$FinagledClient@20ef6b76
scala> Await.result(tweetService.getTweets(GetTweetsRequest(Seq(20))))
res7: Seq[GetTweetResult] = ... "just setting up my twttr" ...
scala> serviceFactory.close
res8: Future[Unit] = ConstFuture(Return(()))
scala> Await.result(tweetService.getTweets(GetTweetsRequest(Seq(20))))
com.twitter.finagle.ServiceClosedException
Это не так уж плохо, но я надеюсь, что есть лучший способ, которого я пока не знаю.
Я не использовал finagle, но согласно документации Finagle
val product = client().flatMap { service =>
// `service` is checked out from the pool.
service(QueryRequest("SELECT 5*5 AS `product`")) map {
case rs: ResultSet => rs.rows.map(processRow)
case _ => Seq.empty
} ensure {
// put `service` back into the pool.
service.close()
}
}
не могли бы вы принять аналогичную стратегию
client.ping().foreach { service =>
logger.info("pong!")
// TODO: close client
service.close()
sys.exit(0)
}