kotlin 如何让Ktor的Application.module()在GraalVM中工作

e0bqpujr  于 2023-11-21  发布在  Kotlin
关注(0)|答案(1)|浏览(168)

我正在尝试开始使用Ktor和GraalVM。我正在尝试使用GraalVM运行一个非常虚拟的Ktor应用程序(IntelliJ的默认应用程序)。
我已经遵循了https://ktor.io/docs/graalvm.html#prepare-for-graalvm的步骤,它工作得很好,因为它直接从embeddedServer调用配置路由。

fun main() {
    embeddedServer(CIO, port = 8080, host = "0.0.0.0") {
        configureRouting()
    }.start(wait = true)

}

字符串
然而,当我重构这段代码时:

fun main() {
    embeddedServer(CIO, port = 8080, host = "0.0.0.0", module = Application::module)
        .start(wait = true)
}

fun Application.module() {
    configureRouting()
}


它停止工作。错误是一个反射问题:

Exception in thread "main" kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Could not compute caller for function: public fun io.ktor.server.application.Application.module(): kotlin.Unit defined in xxxxx[DeserializedSimpleFunctionDescriptor@2ab47469] (member = null)


我在reflect-config.json文件中尝试了很多不同的东西,实际上看起来像:

[
  {
    "name": "kotlin.reflect.jvm.internal.ReflectionFactoryImpl",
    "allDeclaredConstructors": true
  },
  {
    "name": "mypackage.Application",
    "methods": [
      {
        "name": "module",
        "parameterTypes": [],
        "returnType": "kotlin.Unit"
      }
    ]
  },
  {
    "name": "io.ktor.server.application.Application",
    "methods": [
      {
        "name": "module",
        "parameterTypes": [],
        "returnType": "kotlin.Unit"
      }
    ]
  },
  {
    "name": "mypackage.plugins.Routing",
    "allDeclaredConstructors": true
  },
  {
    "name": "kotlin.KotlinVersion",
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allDeclaredMethods": true,
    "allDeclaredConstructors": true
  },
  {
    "name": "kotlin.KotlinVersion[]"
  },
  {
    "name": "kotlin.KotlinVersion$Companion"
  },
  {
    "name": "kotlin.KotlinVersion$Companion[]"
  },
  {
    "name": "kotlin.internal.jdk8.JDK8PlatformImplementations",
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allDeclaredMethods": true,
    "allDeclaredConstructors": true
  }
]


我的项目文件结构看起来像

src/main
├── kotlin
│   └── mypackage
│       ├── Application.kt
│       └── plugins
│           └── Routing.kt
└── resources
    ├── META-INF
    │   └── native-image
    │       └── reflect-config.json
    └── logback.xml


其中Application.kt看起来像前面的代码,而Routing.kt只是:

fun Application.configureRouting() {
    routing {
        get("/") {
            call.respondText("Hello World!")
        }
    }
}


我知道,当直接在embeddedServer上配置路由时,代码可以工作,但在Application.module()函数中委派更方便和更手动。
如果任何人可以提供任何反馈,这将是伟大的。提前感谢!

3phpmpom

3phpmpom1#

为了用graalvm构建ktor,你需要像下面这样运行代理

java -agentlib:native-image-agent=config-output-dir=./graalcnf/ -jar target/ktor-demo-1.0.1-SNAPSHOT-jar-with-dependencies.jar

字符串
这将在graalcnf文件夹下生成reflect json和其他文件,然后您需要在native-image.properties中提供这些文件作为参数,如下所示

Args = --enable-http \
-H:IncludeResources=.*\\.properties \
  -H:ConfigurationFileDirectories=${project.basedir}/graalcnf/


几年前,我为我的测试框架做了这件事,它比较了多个微服务框架,如spring quarkus等。你可以看到示例代码here,你可以在here上看到一些比较

相关问题