【问题标题】:Building non-blocking VertX server with CoroutineVerticle使用 CoroutineVerticle 构建非阻塞 VertX 服务器
【发布时间】:2020-10-26 20:27:36
【问题描述】:

我正在试验 VertX+Couroutines,只是想检查一下这个设置是否在任何时候都被阻塞或有我需要注意的潜在问题。

例如,runBlocking 在这种情况下是否被正确使用,还是我应该使用deployVerticle?然后在 requestHandler 内部,我正在做 GlobalScope.launch,这似乎不鼓励,这里使用的正确范围是什么?

我已将 VertX 4.0.0-milestone5 添加到我的 Gradle 构建脚本中,我没有使用 VertX Web:

            val vertxVersion = "4.0.0-milestone5"
            implementation("io.vertx:vertx-core:$vertxVersion") {
                exclude(group = "com.fasterxml.jackson.core", module = "jackson-core")
                exclude(group = "com.fasterxml.jackson.core", module = "jackson-databind")
                exclude(group = "log4j", module = "log4j")
                exclude(group = "org.apache.logging.log4j", module = "log4j-api")
                exclude(group = "org.apache.logging.log4j", module = "log4j-core")

            }
            implementation("io.vertx:vertx-lang-kotlin:$vertxVersion")
            implementation("io.vertx:vertx-lang-kotlin-coroutines:$vertxVersion")

Routing.kt 内部我有以下设置:

class Routing(
    private val port: Int
) : CoroutineVerticle() {

    override suspend fun start() {

        Vertx.vertx().createHttpServer(
            HttpServerOptions().setCompressionSupported(true)
        ).requestHandler { req ->
            GlobalScope.launch {
                try {

                    log.info("${req.method()}:${req.path()}")

                    req.response().setStatusCode(200).end("Hello World")
                } catch (e: Exception) {
                    log.error(e.message ?: "", e)
                    req.response().setStatusCode(500).end("Something Went Wrong")
                }
            }
        }.listen(port)

        log.info("Listening on $port")

    }


    override suspend fun stop() {

    }

    companion object {

        private val log = LoggerFactory.getLogger(Routing::class.java)
        private val root = RoutingTree()

        suspend fun setup(port: Int) {
            Endpoint.all.forEach {
                root.addPath(it.key, it.value)
            }
            log.info("\n" + root.toString())
            Routing(port = port).start()
        }
    }

}

这个Routing.setup 然后在main() 中使用

object Server {

    private val log = LoggerFactory.getLogger(this.javaClass)

    @JvmStatic
    @ExperimentalTime
    fun main(args: Array<String>) = runBlocking {

        ....

        // setup routing
        Routing.setup(
            port = if (ENV.env == LOCAL) {
                5555
            } else {
                80
            },
        ) 

【问题讨论】:

    标签: kotlin vert.x kotlin-coroutines


    【解决方案1】:

    Kotlin 与 Vert.x 集成的重点在于您不必使用 GlobalScope.launch

    这是一个如何实现它的最小示例:

    fun main() {
        val vertx = Vertx.vertx()
    
        vertx.deployVerticle("Server")
    }
    
    class Server : CoroutineVerticle() {
        override suspend fun start() {
            vertx.createHttpServer().requestHandler { req ->
                // You already have access to all coroutine generators
                launch {
                    // In this scope you can use suspending functions
                    delay(1000)
                    req.response().end("Done!")
                }
            }.listen(8888)
        }
    }
    

    【讨论】:

    • 我不得不更改一行vertx.deployVerticle(Server()),然后它就完美运行了。在我的问题中,启动会触发错误,而在您的示例中它可以工作,因此要进行一些重构以利用 deployVerticle 样式。感谢您的精彩回答!
    猜你喜欢
    • 2010-11-30
    • 2022-12-09
    • 2015-04-25
    • 1970-01-01
    • 1970-01-01
    • 2015-11-25
    • 2017-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多