使用 CoroutineVerticle 构建非阻塞 VertX 服务器
Building non-blocking VertX server with CoroutineVerticle
我正在试验 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 集成的全部意义在于您不必使用 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+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 集成的全部意义在于您不必使用 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)
}
}