如何在Ktor内部检查Netty实际上已启动?

时间:2019-05-03 16:03:05

标签: kotlin netty ktor

我需要对Ktor应用进行一些初始化,但是我只想在Netty准备好接受连接之后再进行。另一方面,如果Netty无法启动(例如,典型的“地址已在使用中”),我不希望发生这种初始化。

我实现了直接的方法(见下文),但我想知道是否有可能使它成为不太丑的方法

首先,我保存对NettyApplicationEngine的引用:

embeddedServer = embeddedServer(Netty, port, module)

然后我使用NettyApplicationEngine中的channels字段来确定其状态:

private fun NettyApplicationEngine.channelsReady(): Boolean {
    val channelsField = this::class.members.find { it.name == "channels" }!!
    channelsField.isAccessible = true
    val channels = channelsField.call(this) as List<Channel>?
    return !channels.isNullOrEmpty() && channels.all { it.isActive }
}

最后,我捕获到ApplicationStarted事件并旋转直到通道准备就绪:

environment.monitor.subscribe(ApplicationStarted) {
        thread(start = true, name = "real netty postinit") {
            for (i in 1..100) {
                TimeUnit.MILLISECONDS.sleep(100)
                if (embeddedServer.channelsReady()) break
            }

            if (embeddedServer.channelsReady()) {
                // Initialization here
            } else {
                // Server didn't start
                embeddedServer.stop(1, 1, TimeUnit.SECONDS)
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

尝试了几种不同的方法后,我得出了一个自测结论,该测验仅将HTTP请求发送到自己的端点,并且如果HttpClient和路由处理程序都成功执行,则我认为Netty已经准备就绪。

首先,我向Routing.RoutingCallFinished注册NettyApplicationEngine.environment.monitor事件(稍后我dispose创建一个处理程序)。

然后,我迭代所有NettyApplicationEngine.environment.connectors并创建将由Deferred处理程序完成的RoutingCallFinished。此外,我启动了异步协程,这些协程将使用HttpClient检查相应的端点。

此后,我awaitAll在那些Deferred上(以及Deferred事件处理程序的ApplicationStarted上)。