Как закрыть клиент 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)
  }
Другие вопросы по тегам