如何在Ktor内部检查Netty是否真正启动了?

问题描述 投票:0回答:2

我需要对我的 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)
            }
        }
    }
kotlin netty ktor
2个回答
2
投票

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

首先,我使用

Routing.RoutingCallFinished
注册
NettyApplicationEngine.environment.monitor
事件(稍后我会
dispose
创建的处理程序)。

然后我迭代所有

NettyApplicationEngine.environment.connectors
并创建将从
Deferred
处理程序完成的
RoutingCallFinished
。另外,我启动了异步协程,它将使用 HttpClient 检查相应的端点。

之后,我在那些

awaitAll
Deferred
(以及来自
Deferred
事件处理程序的
ApplicationStarted
)。


0
投票

根据文档,正确的方法是创建一个监视器。

我是这样做的

private var serverStarted = false

fun Application.module() {

    monitor.subscribe(ApplicationStarted) {
        serverStarted = true
    }

    monitor.subscribe(ApplicationStopped) {
        serverStarted = false
    }

    // The rest of the module code goes here
}

到目前为止似乎运作良好。

© www.soinside.com 2019 - 2024. All rights reserved.