Skip to content
Server Plugin

在 Ktor 服务器中跟踪请求

所需依赖项: io.ktor:ktor-server-call-id

代码示例: call-id

原生服务器
Ktor 支持 Kotlin/Native,并允许您无需额外运行时或虚拟机即可运行服务器。
支持: ✅

CallId 插件允许您使用唯一的请求 ID 或调用 ID 端到端地跟踪客户端请求。通常,在 Ktor 中使用调用 ID 的流程如下:

  1. 首先,您需要通过以下方式之一为特定请求获取一个调用 ID:
    • 反向代理(例如 Nginx)或云服务提供商(例如 Heroku)可能会在特定请求头中添加调用 ID,例如 X-Request-Id。在这种情况下,Ktor 允许您检索调用 ID。
    • 否则,如果请求未包含调用 ID,您可以在 Ktor 服务器上生成它。
  2. 接下来,Ktor 使用预定义字典验证检索/生成的调用 ID。您也可以提供自己的条件来验证调用 ID。
  3. 最后,您可以将调用 ID 在特定请求头中发送给客户端,例如 X-Request-Id

CallIdCallLogging 结合使用,有助于您通过将调用 ID 放入 MDC 上下文并配置日志记录器以显示每个请求的调用 ID 来排查调用问题。

在客户端,Ktor 提供了 CallId 插件来跟踪客户端请求。

添加依赖项

要使用 CallId,您需要在构建脚本中包含 ktor-server-call-id 构件:

Kotlin
Groovy
XML

安装 CallId

要将 安装 CallId 插件到应用程序, 请在指定的

模块
模块允许您通过分组路由来构建应用程序。
中将其传递给 install 函数。 以下代码片段展示了如何安装 CallId ...

  • ... 在 embeddedServer 函数调用内部。
  • ... 在显式定义的 module 内部,它是 Application 类的一个扩展函数。
kotlin
kotlin

配置 CallId

检索调用 ID

CallId 提供了几种检索调用 ID 的方法:

  • 要从指定请求头中检索调用 ID,请使用 retrieveFromHeader 函数,例如:

    kotlin
    install(CallId) {
        retrieveFromHeader(HttpHeaders.XRequestId)
    }

    您还可以使用 header 函数在同一个请求头中检索并发送调用 ID

  • 如果需要,您可以从 ApplicationCall 中检索调用 ID:

    kotlin
    install(CallId) {
        retrieve { call ->
            call.request.header(HttpHeaders.XRequestId)
        }
    }

请注意,所有检索到的调用 ID 都将使用默认字典进行验证

生成调用 ID

如果传入请求不包含调用 ID,您可以使用 generate 函数生成它:

  • 以下示例展示了如何从预定义字典中生成具有特定长度的调用 ID:
    kotlin
    install(CallId) {
        generate(10, "abcde12345")
    }
  • 在以下示例中,generate 函数接受一个用于生成调用 ID 的代码块:
    kotlin
    install(CallId) {
        val counter = atomic(0)
        generate {
            "generated-call-id-${counter.getAndIncrement()}"
        }
    }

验证调用 ID

所有检索/生成的调用 ID 都将使用默认字典进行验证,其内容如下:

kotlin
CALL_ID_DEFAULT_DICTIONARY: String = "abcdefghijklmnopqrstuvwxyz0123456789+/=-"

这意味着包含大写字母的调用 ID 将无法通过验证。如果需要,您可以通过使用 verify 函数来应用更宽松的规则:

kotlin
install(CallId) {
    verify { callId: String ->
        callId.isNotEmpty()
    }
}

您可以在此处找到完整示例:call-id

将调用 ID 发送给客户端

检索/生成调用 ID 后,您可以将其发送给客户端:

  • 使用 header 函数可以在同一个请求头中检索并发送调用 ID

    kotlin
    install(CallId) {
        header(HttpHeaders.XRequestId)
    }

    您可以在此处找到完整示例:call-id

  • replyToHeader 函数将在指定请求头中发送调用 ID:

    kotlin
    install(CallId) {
        replyToHeader(HttpHeaders.XRequestId)
    }
  • 如果需要,您可以使用 ApplicationCall响应中发送调用 ID:

    kotlin
    reply { call, callId ->
        call.response.header(HttpHeaders.XRequestId, callId)
    }

将调用 ID 放入 MDC

CallIdCallLogging 结合使用,有助于您通过将调用 ID 放入 MDC 上下文并配置日志记录器以显示每个请求的调用 ID 来排查调用问题。为此,请在 CallLogging 配置代码块内部调用 callIdMdc 函数,并指定要放入 MDC 上下文中的所需键:

kotlin
install(CallLogging) {
    callIdMdc("call-id")
}

此键可以传递给日志记录器配置以在日志中显示调用 ID。例如,logback.xml 文件可能如下所示:

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %X{call-id} %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

您可以在此处找到完整示例:call-id