Create a custom ApplicationEngine

预计阅读时间:3分钟

Ktor的HTTP客户端和服务器提供了一个公共接口,同时允许使用多个不同的引擎来执行和处理HTTP请求.

Ktor包含几个工件和引擎:

  • 对于服务器: NettyJettyTomcatCIOTestEngine
  • 对于客户端: ApacheEngineJettyHttp2EngineCIOEngineTestHttpClientEngine

ApplicationEngine API

ApplicationEngine简化版本如下所示:

ApplicationEngineInterface.kt
interface ApplicationEngineFactory<
    out TEngine : ApplicationEngine,
    TConfiguration : ApplicationEngine.Configuration
> {
    fun create(environment: ApplicationEngineEnvironment, configure: TConfiguration.() -> Unit): TEngine
}

interface ApplicationEngine {
    val environment: ApplicationEngineEnvironment
    fun start(wait: Boolean = false): ApplicationEngine
    fun stop(gracePeriod: Long, timeout: Long, timeUnit: TimeUnit)

    open class Configuration {
        val parallelism: Int
        var connectionGroupSize: Int
        var workerGroupSize: Int
        var callGroupSize: Int
    }
}

interface ApplicationEngineEnvironment {
    val connectors: List<EngineConnectorConfig>
    val application: Application
    fun start()
    fun stop()

    val classLoader: ClassLoader
    val log: Logger
    val config: ApplicationConfig
    val monitor: ApplicationEvents
}

interface EngineConnectorConfig {
    val type: ConnectorType
    val host: String
    val port: Int
}

data class ConnectorType(val name: String) {
    companion object {
        val HTTP = ConnectorType("HTTP")
        val HTTPS = ConnectorType("HTTPS")
    }
}

abstract class BaseApplicationEngine(
    final override val environment: ApplicationEngineEnvironment,
    val pipeline: EnginePipeline = defaultEnginePipeline(environment)
) : ApplicationEngine {
    val application: Application
}

ApplicationEngineFactory

ApplicationEngineFactory每个实现以及子类型ApplicationEngine.Configuration定义了每个引擎的公开API.

fun ApplicationEngineFactory.create(environment: ApplicationEngineEnvironment, configure: TConfiguration.() -> Unit): TEngine

ApplicationEngineFactory.create实例化正确的子类型ApplicationEngine.Configuration并调用提供的configure: TConfiguration.() -> Unit应当使配置对象发生变化的configure: TConfiguration.() -> Unit lambda. 它还构造了ApplicationEngine的实现,很可能是BaseApplicationEngine的子类型.

例如:

class MyApplicationEngineFactory
    <MyApplicationEngine, MyApplicationEngineConfiguration>
{

    fun create(
        environment: ApplicationEngineEnvironment,
        configure: MyApplicationEngineConfiguration.() -> Unit
    ): MyApplicationEngine {
    
        val configuration = MyApplicationEngineConfiguration()
        configure(configuration)
        return MyApplicationEngine(environment, configuration)
    }
    
}

BaseApplicationEngine

具有BaseApplicationEngine的抽象实现的ApplicationEngine接口启动和停止该应用程序. 它包含ApplicationEngineEnvironment以及ApplicationEngineEnvironment的构造配置.

此类有两种方法:

  • start方法:(从环境)连接到ApplicationEngineEnvironment.connectors ,启动环境,然后启动并配置引擎以使用ApplicationCall为每个HTTP请求触发application管道的执行.
  • stop方法:停止引擎和环境,并取消注册由start方法注册的所有项目.

BaseApplicationEngine公开传递给构造函数的ApplicationEngineEnvironment ,并创建一个EnginePipeline ,用作预先拦截应用程序管道的中介. 它还将默认转换安装在发送和接收管道中,并记录已定义的连接端点.

例如:

class MyApplicationEngine(
    environment: ApplicationEngineEnvironment,
    configuration: MyApplicationEngineConfiguration
) : BaseApplicationEngine(environment) {
    val myEngine = MyEngine()

    override fun start(wait: Boolean): MyApplicationEngine {
        environment.start()
        myEngine.start()
        myEngine.addRequestHandler(::handleRequest)
        return this
    }
    
    override fun stop(gracePeriod: Long, timeout: Long, timeUnit: TimeUnit) {
        myEngine.removeRequestHandler(::handleRequest)
        myEngine.stop()
        environment.stop()
    }
    
    private fun handleRequest(request: MyEngineCall) {
        val call: ApplicationCall = request.toApplicationCall()
        pipeline.execute(call)
    }
}

by  ICOPY.SITE