What Happens in a Server?

预计阅读时间:6分钟

Ktor的设计具有灵活性和可扩展性. 它由小的,简单的部分组成,但是如果您不知道发生了什么,那么它就像一个黑盒子.

在本节中,您将发现Ktor在幕后所做的事情,并且将了解有关其通用基础结构的更多信息.

目录:

Entry points

您可以通过多种方式运行Ktor应用程序:

Start-up

Common

ApplicationEngineEnvironment:

首先,必须建立一个不变的环境. 使用classLoader,记录器, 配置 ,充当应用程序事件的事件总线的监视器以及一组连接器和模块,它们将构成应用程序和watchPath .

您可以使用ApplicationEngineEnvironmentBuilder以及方便的DSL功能applicationEngineEnvironmentcommandLineEnvironment来构建它.

ApplicationEngine:

有多个ApplicationEngine ,每个受支持的服务器一个,例如:Netty,Jetty,CIO或Tomcat.

应用程序引擎是负责运行应用程序的类,它具有特定的配置和相关的环境,并且可以startstop .

启动特定的应用程序引擎时,它将使用提供的配置通过指定的工作程序通过SSL,证书等来侦听正确的端口和主机.

连接器将用于侦听特定的http / https主机和端口. 而Application管道将用于处理请求.

Application Pipeline:

它是由ApplicationEngineEnvironment创建的,最初为空. 这是一个没有主题的管道,该管道具有ApplicationCall作为上下文. 创建环境后,将调用每个指定的模块来配置此应用程序.

embeddedServer

当您运行自己的main方法并调用embeddedServer函数时,您将提供一个特定的ApplicationEngineFactory ,然后将创建或提供一个ApplicationEngineEnvironment .

EngineMain

Ktor为每个受支持的服务器引擎定义一个EngineMain类. 此类定义了可以执行以运行应用程序的main方法. 通过使用commandLineEnvironment ,它将从您的资源中加载HOCON application.conf文件,并将使用其他参数来确定要安装的模块以及如何配置服务器.

这些类通常在CommandLine.kt源文件中声明.

TestApplicationEngine

对于测试,Ktor定义了一个TestApplicationEnginewithTestApplication方便的方法,该方法将允许您测试应用程序模块,管道和其他功能,而无需实际启动任何服务器或模拟任何功能. 它将使用内存中的配置MapApplicationConfig("ktor.deployment.environment" to "test") ,您可以用来确定它是否要在测试环境中运行.

Monitor events

与环境相关联的是Ktor用于引发应用程序事件的监视器实例. 您可以使用它来订阅事件. 例如,您可以订阅停止应用程序事件以关闭特定服务或完成某些资源.

Ktor定义的事件列表:

val ApplicationStarting = EventDefinition<Application>()
val ApplicationStarted = EventDefinition<Application>()
val ApplicationStopPreparing = EventDefinition<ApplicationEnvironment>()
val ApplicationStopping = EventDefinition<Application>()
val ApplicationStopped = EventDefinition<Application>()

Pipelines

Ktor定义了用于异步可扩展计算的管道. 整个Ktor都使用管道.

所有管道都具有关联的主题类型, 上下文类型以及与拦截器关联的阶段列表. 以及充当小型对象容器的属性 .

阶段是有序的,可以定义为在另一个阶段之后或之前或结束时执行.

每个管道都具有该实例的阶段上下文的有序列表,其中包含每个阶段的一组拦截器.

例如:

  • Pipeline
    • Phase1
      • Interceptor1
      • Interceptor2
    • Phase2
      • Interceptor3
      • Interceptor4

这里的想法是,特定阶段的每个拦截器都不依赖于同一阶段的其他拦截器,而是依赖于先前阶段的拦截器.

当执行管道时,所有注册的拦截器将按照阶段定义的顺序执行.

ApplicationCallPipeline

Ktor的服务器部分限定ApplicationCallPipeline无主体并用ApplicationCall作为上下文. Application实例是ApplicationCallPipeline .

因此,当服务器的应用程序引擎处理HTTP请求时,它将执行Application管道.

上下文类ApplicationCall包含应用程序, requestresponse以及attributesparameters .

最后,应用程序模块将结束为应用程序管道的特定阶段注册拦截器,以处理request并发出response .

ApplicationCallPipeline为其管道定义以下内置阶段:

val Setup = PipelinePhase("Setup") // Phase for preparing the call, and processing attributes
val Monitoring = PipelinePhase("Monitoring") // Phase for tracing calls: logging, metrics, error handling etc. 
val Features = PipelinePhase("Features") // Phase for infrastructure features, most intercept at this phase
val Call = PipelinePhase("Call") // Phase for processing a call and sending a response
val Fallback = PipelinePhase("Fallback") // Phase for handling unprocessed calls

Features

Ktor使用ApplicationFeature类定义应用程序功能. 功能是可以install到特定管道的东西. 它可以访问管道,并且可以注册拦截器并执行其他各种操作.

Routing

To illustrate how features and a pipeline tree work together, let’s have a look at how Routing works.

路由和其他功能一样,通常是这样安装的:

install(Routing) { }

但是有一个简单的方法可以注册并开始使用它,如果已经注册,它也可以安装它:

routing { }

路由定义为一棵树,其中每个节点都是一个Route ,也是一个ApplicationCallPipeline的单独实例. 因此,当执行根路由节点时,它将执行自己的管道. 并且在处理完路线后将停止执行操作.

What’s next

by  ICOPY.SITE