如何在 Ktor 内部检查 Netty 是不是实际启动?
Posted
技术标签:
【中文标题】如何在 Ktor 内部检查 Netty 是不是实际启动?【英文标题】:How to check inside Ktor that the Netty is actually started?如何在 Ktor 内部检查 Netty 是否实际启动? 【发布时间】:2019-09-22 05:13:42 【问题描述】:我需要对我的 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】:在尝试了几种不同的方法后,我以自检结束,它只是将 HTTP 请求发送到我自己的端点,如果 HttpClient 和路由处理程序都成功执行,我认为 Netty 已经准备好了。
首先我向NettyApplicationEngine.environment.monitor
注册Routing.RoutingCallFinished
事件(稍后我将dispose
创建处理程序)。
然后我迭代所有NettyApplicationEngine.environment.connectors
并创建Deferred
s,它将从RoutingCallFinished
处理程序中完成。另外,我启动了异步协程,它将使用 HttpClient 检查相应的端点。
之后我在那些Deferred
s 上awaitAll
(以及来自ApplicationStarted
事件处理程序的Deferred
)。
【讨论】:
以上是关于如何在 Ktor 内部检查 Netty 是不是实际启动?的主要内容,如果未能解决你的问题,请参考以下文章
如何修复 io.ktor.server.engine.CommandLineKt 在 gradle/kotlin/netty 项目中抛出的“既未指定端口也未指定 sslPort”?