or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application.mdconfiguration.mdengine.mdindex.mdrequest-response.mdrouting.md

engine.mddocs/

0

# Server Engines

1

2

Ktor's server engine system provides flexible deployment options through multiple engine implementations. The engine architecture separates application logic from server infrastructure, enabling the same application to run on different server technologies.

3

4

## ApplicationEngine Interface

5

6

### Core Engine Interface

7

8

```kotlin { .api }

9

interface ApplicationEngine {

10

val environment: ApplicationEnvironment

11

12

fun start(wait: Boolean = false): ApplicationEngine

13

suspend fun startSuspend(wait: Boolean = false): ApplicationEngine

14

fun stop(gracePeriodMillis: Long = 500, timeoutMillis: Long = 500)

15

suspend fun resolvedConnectors(): List<EngineConnectorConfig>

16

}

17

```

18

19

### Engine Lifecycle

20

21

```kotlin { .api }

22

// Start server and optionally wait

23

val engine = embeddedServer(Netty, port = 8080) {

24

routing {

25

get("/") { call.respondText("Hello!") }

26

}

27

}

28

29

// Start without blocking

30

engine.start(wait = false)

31

32

// Start with blocking (typical for main function)

33

engine.start(wait = true)

34

35

// Start asynchronously

36

runBlocking {

37

engine.startSuspend(wait = false)

38

// Do other work

39

delay(1000)

40

engine.stop(1000, 5000)

41

}

42

43

// Stop with grace period and timeout

44

engine.stop(

45

gracePeriodMillis = 1000, // Allow 1 second for graceful shutdown

46

timeoutMillis = 5000 // Force shutdown after 5 seconds

47

)

48

```

49

50

## ApplicationEngineFactory Interface

51

52

### Engine Factory

53

54

```kotlin { .api }

55

interface ApplicationEngineFactory<TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> {

56

fun create(

57

environment: ApplicationEnvironment,

58

configure: TConfiguration.() -> Unit = {}

59

): TEngine

60

}

61

```

62

63

### Available Engine Factories

64

65

```kotlin { .api }

66

// Netty engine (high-performance NIO)

67

object Netty : ApplicationEngineFactory<NettyApplicationEngine, NettyApplicationEngine.Configuration>

68

69

// CIO engine (coroutine-based)

70

object CIO : ApplicationEngineFactory<CIOApplicationEngine, CIOApplicationEngine.Configuration>

71

72

// Jetty engine (traditional servlet)

73

object Jetty : ApplicationEngineFactory<JettyApplicationEngine, JettyApplicationEngine.Configuration>

74

75

// Tomcat engine (traditional servlet)

76

object Tomcat : ApplicationEngineFactory<TomcatApplicationEngine, TomcatApplicationEngine.Configuration>

77

```

78

79

## Embedded Server Creation

80

81

### Basic Embedded Server

82

83

```kotlin { .api }

84

// Create embedded server with factory and configuration

85

fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> embeddedServer(

86

factory: ApplicationEngineFactory<TEngine, TConfiguration>,

87

port: Int = 80,

88

host: String = "0.0.0.0",

89

configure: TConfiguration.() -> Unit = {},

90

module: Application.() -> Unit

91

): EmbeddedServer<TEngine, TConfiguration>

92

93

// Simple embedded server

94

fun main() {

95

embeddedServer(Netty, port = 8080) {

96

routing {

97

get("/") {

98

call.respondText("Hello, Ktor!")

99

}

100

}

101

}.start(wait = true)

102

}

103

```

104

105

### Advanced Embedded Server

106

107

```kotlin { .api }

108

// Create embedded server with environment

109

fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> embeddedServer(

110

factory: ApplicationEngineFactory<TEngine, TConfiguration>,

111

environment: ApplicationEnvironment,

112

configure: TConfiguration.() -> Unit = {}

113

): EmbeddedServer<TEngine, TConfiguration>

114

115

// Example with custom environment

116

fun main() {

117

val environment = applicationEnvironment {

118

config = HoconApplicationConfig(ConfigFactory.load())

119

log = LoggerFactory.getLogger("Application")

120

}

121

122

embeddedServer(Netty, environment) {

123

// Netty-specific configuration

124

connectionGroupSize = 2

125

workerGroupSize = 5

126

callGroupSize = 10

127

128

connector {

129

port = 8080

130

host = "0.0.0.0"

131

}

132

133

connector {

134

port = 8443

135

host = "0.0.0.0"

136

// SSL configuration would go here

137

}

138

}.start(wait = true)

139

}

140

```

141

142

## Engine Configuration

143

144

### Base Engine Configuration

145

146

```kotlin { .api }

147

open class ApplicationEngine.Configuration {

148

var parallelism: Int = availableProcessors()

149

var connectionGroupSize: Int = parallelism

150

var workerGroupSize: Int = parallelism

151

var callGroupSize: Int = parallelism

152

var shutdownGracePeriod: Long = 1000

153

var shutdownTimeout: Long = 5000

154

155

internal val connectors = mutableListOf<EngineConnectorConfig>()

156

157

fun takeFrom(other: Configuration) {

158

// Copy configuration from another instance

159

parallelism = other.parallelism

160

connectionGroupSize = other.connectionGroupSize

161

workerGroupSize = other.workerGroupSize

162

callGroupSize = other.callGroupSize

163

shutdownGracePeriod = other.shutdownGracePeriod

164

shutdownTimeout = other.shutdownTimeout

165

}

166

}

167

```

168

169

### Connector Configuration

170

171

```kotlin { .api }

172

interface EngineConnectorConfig {

173

val type: ConnectorType

174

val host: String

175

val port: Int

176

}

177

178

enum class ConnectorType {

179

HTTP, HTTPS

180

}

181

182

// Configure connectors

183

embeddedServer(Netty, port = 8080) {

184

// Default connector is automatically created

185

186

// Add additional connectors

187

connector {

188

port = 8443

189

host = "0.0.0.0"

190

// Additional connector configuration

191

}

192

}

193

```

194

195

## Base Engine Implementation

196

197

### BaseApplicationEngine

198

199

```kotlin { .api }

200

abstract class BaseApplicationEngine(

201

environment: ApplicationEnvironment,

202

pipeline: EnginePipeline

203

) : ApplicationEngine {

204

205

override val environment: ApplicationEnvironment = environment

206

207

// Lifecycle management

208

abstract suspend fun startServer(): Unit

209

abstract suspend fun stopServer(): Unit

210

211

// Resolved connector information

212

override fun resolvedConnectors(): List<EngineConnectorConfig>

213

}

214

```

215

216

### Base Call Implementation

217

218

```kotlin { .api }

219

abstract class BaseApplicationCall(

220

application: Application

221

) : ApplicationCall {

222

223

override val application: Application = application

224

override val attributes: Attributes = Attributes()

225

226

abstract override val request: BaseApplicationRequest

227

abstract override val response: BaseApplicationResponse

228

229

// Parameter resolution

230

private val _parameters = lazy {

231

request.queryParameters + request.rawParameters

232

}

233

override val parameters: Parameters get() = _parameters.value

234

}

235

236

abstract class BaseApplicationRequest(call: ApplicationCall) : ApplicationRequest

237

abstract class BaseApplicationResponse(call: ApplicationCall) : ApplicationResponse

238

```

239

240

## Engine Pipeline

241

242

### EnginePipeline

243

244

```kotlin { .api }

245

class EnginePipeline(

246

val developmentMode: Boolean = false

247

) : Pipeline<Unit, ApplicationCall>(Before, Call) {

248

249

companion object {

250

val Before = PipelinePhase("Before")

251

val Call = PipelinePhase("Call")

252

}

253

}

254

255

// Default engine pipeline creation

256

fun defaultEnginePipeline(

257

environment: ApplicationEnvironment

258

): EnginePipeline {

259

return EnginePipeline(environment.developmentMode)

260

}

261

```

262

263

### Default Pipeline Implementation

264

265

```kotlin { .api }

266

class DefaultEnginePipeline(

267

application: Application,

268

developmentMode: Boolean = false

269

) : EnginePipeline(developmentMode) {

270

271

init {

272

// Install default pipeline phases and interceptors

273

intercept(Call) {

274

try {

275

// Execute application call pipeline

276

application.execute(call)

277

} catch (e: Throwable) {

278

handleEngineException(e)

279

}

280

}

281

}

282

}

283

```

284

285

## Environment and Configuration

286

287

### ApplicationEnvironment

288

289

```kotlin { .api }

290

interface ApplicationEnvironment {

291

val rootPath: String

292

val log: Logger

293

val config: ApplicationConfig

294

val monitor: Events

295

val developmentMode: Boolean

296

val parentCoroutineContext: CoroutineContext

297

val watchPaths: List<String>

298

}

299

```

300

301

### ApplicationEnvironmentBuilder

302

303

```kotlin { .api }

304

class ApplicationEnvironmentBuilder {

305

var rootPath: String = ""

306

var log: Logger = LoggerFactory.getLogger("Application")

307

var config: ApplicationConfig = MapApplicationConfig()

308

var developmentMode: Boolean = false

309

var parentCoroutineContext: CoroutineContext? = null

310

val watchPaths: MutableList<String> = mutableListOf()

311

312

fun build(): ApplicationEnvironment

313

}

314

315

// Create application environment

316

fun applicationEnvironment(

317

block: ApplicationEnvironmentBuilder.() -> Unit = {}

318

): ApplicationEnvironment {

319

return ApplicationEnvironmentBuilder().apply(block).build()

320

}

321

```

322

323

### Environment Configuration

324

325

```kotlin { .api }

326

// Configure environment from config file/object

327

fun ApplicationEnvironmentBuilder.configure(

328

config: ApplicationConfig

329

) {

330

this.config = config

331

332

// Extract common configuration

333

rootPath = config.propertyOrNull("ktor.deployment.rootPath")?.getString() ?: ""

334

developmentMode = config.propertyOrNull("ktor.development")?.getString()?.toBoolean() ?: false

335

336

// Configure watch paths for development

337

config.configList("ktor.deployment.watch").forEach { watchConfig ->

338

watchPaths.add(watchConfig.property("path").getString())

339

}

340

}

341

342

// Example configuration usage

343

fun createEnvironment(): ApplicationEnvironment {

344

return applicationEnvironment {

345

config = HoconApplicationConfig(ConfigFactory.load())

346

configure(config)

347

348

log = LoggerFactory.getLogger("MyApp")

349

developmentMode = System.getenv("ENVIRONMENT") != "production"

350

}

351

}

352

```

353

354

## Deployment Configuration

355

356

### Command Line Configuration

357

358

```kotlin { .api }

359

class CommandLineConfig(args: Array<String>) {

360

val port: Int

361

val host: String

362

val configPath: String?

363

val developmentMode: Boolean

364

365

// Parse command line arguments

366

init {

367

// Implementation parses -port, -host, -config, -dev arguments

368

}

369

}

370

371

// Configuration keys

372

object ConfigKeys {

373

const val applicationIdPath = "ktor.application.id"

374

const val hostConfigPath = "ktor.deployment.host"

375

const val portConfigPath = "ktor.deployment.port"

376

const val shutdownGracePeriodPath = "ktor.deployment.shutdown.gracePeriod"

377

const val shutdownTimeoutPath = "ktor.deployment.shutdown.timeout"

378

}

379

```

380

381

### Configuration Loading

382

383

```kotlin { .api }

384

// Load common configuration from ApplicationConfig

385

fun ApplicationEngine.Configuration.loadCommonConfiguration(config: ApplicationConfig) {

386

config.propertyOrNull("ktor.deployment.shutdown.gracePeriod")?.getString()?.toLong()?.let {

387

shutdownGracePeriod = it

388

}

389

390

config.propertyOrNull("ktor.deployment.shutdown.timeout")?.getString()?.toLong()?.let {

391

shutdownTimeout = it

392

}

393

394

config.propertyOrNull("ktor.deployment.connectionGroupSize")?.getString()?.toInt()?.let {

395

connectionGroupSize = it

396

}

397

398

config.propertyOrNull("ktor.deployment.workerGroupSize")?.getString()?.toInt()?.let {

399

workerGroupSize = it

400

}

401

}

402

```

403

404

## Utility Functions

405

406

### Shutdown Hooks

407

408

```kotlin { .api }

409

// Add shutdown hook to embedded server

410

fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration>

411

EmbeddedServer<TEngine, TConfiguration>.addShutdownHook() {

412

Runtime.getRuntime().addShutdownHook(Thread {

413

stop(1000, 5000)

414

})

415

}

416

417

// Example usage

418

fun main() {

419

val server = embeddedServer(Netty, port = 8080) {

420

routing {

421

get("/") { call.respondText("Hello!") }

422

}

423

}

424

425

server.addShutdownHook()

426

server.start(wait = true)

427

}

428

```

429

430

### Coroutine Integration

431

432

```kotlin { .api }

433

// Stop server when coroutine context is cancelled

434

suspend fun ApplicationEngine.stopServerOnCancellation() {

435

try {

436

awaitCancellation()

437

} finally {

438

stopSuspend(1000, 5000)

439

}

440

}

441

442

// Usage with structured concurrency

443

fun main() = runBlocking {

444

val server = embeddedServer(Netty, port = 8080) {

445

routing {

446

get("/") { call.respondText("Hello!") }

447

}

448

}

449

450

launch {

451

server.start()

452

server.stopServerOnCancellation()

453

}

454

455

// Server will stop when this coroutine scope completes

456

delay(60000) // Run for 1 minute

457

}

458

```

459

460

## Exception Handling

461

462

### Default Exception Handler

463

464

```kotlin { .api }

465

// Default uncaught exception handler for engines

466

class DefaultUncaughtExceptionHandler : Thread.UncaughtExceptionHandler {

467

override fun uncaughtException(t: Thread, e: Throwable) {

468

// Log uncaught exceptions

469

logger.error("Uncaught exception in thread ${t.name}", e)

470

}

471

}

472

473

// Map exceptions to HTTP status codes

474

fun defaultExceptionStatusCode(exception: Throwable): HttpStatusCode {

475

return when (exception) {

476

is NotFoundException -> HttpStatusCode.NotFound

477

is ParameterConversionException -> HttpStatusCode.BadRequest

478

is UnsupportedMediaTypeException -> HttpStatusCode.UnsupportedMediaType

479

is PayloadTooLargeException -> HttpStatusCode.PayloadTooLarge

480

else -> HttpStatusCode.InternalServerError

481

}

482

}

483

```

484

485

## Deployment Examples

486

487

### Production Deployment

488

489

```kotlin { .api }

490

fun main() {

491

val environment = applicationEnvironment {

492

// Load configuration from application.conf

493

config = HoconApplicationConfig(ConfigFactory.load())

494

495

// Configure from config file

496

configure(config)

497

498

// Production settings

499

developmentMode = false

500

log = LoggerFactory.getLogger("ProductionApp")

501

}

502

503

val server = embeddedServer(Netty, environment) {

504

// Production configuration

505

connectionGroupSize = 4

506

workerGroupSize = 8

507

callGroupSize = 16

508

509

shutdownGracePeriod = 5000

510

shutdownTimeout = 10000

511

512

// Multiple connectors for different interfaces

513

connector {

514

port = 8080

515

host = "0.0.0.0"

516

}

517

518

connector {

519

port = 8443

520

host = "0.0.0.0"

521

// SSL configuration

522

}

523

524

connector {

525

port = 9090

526

host = "127.0.0.1" // Internal management interface

527

}

528

}

529

530

// Add shutdown hook for graceful termination

531

server.addShutdownHook()

532

533

// Start server

534

server.start(wait = true)

535

}

536

```

537

538

### Development Deployment

539

540

```kotlin { .api }

541

fun main() {

542

val server = embeddedServer(Netty, port = 8080) {

543

// Development configuration - optimized for fast restarts

544

connectionGroupSize = 1

545

workerGroupSize = 1

546

callGroupSize = 1

547

548

connector {

549

port = 8080

550

host = "127.0.0.1" // Local only

551

}

552

}

553

554

Runtime.getRuntime().addShutdownHook(Thread {

555

server.stop(100, 1000) // Faster shutdown for development

556

})

557

558

server.start(wait = true)

559

}

560

```

561

562

### Multi-Application Deployment

563

564

```kotlin { .api }

565

fun main() {

566

// Create shared environment

567

val sharedEnvironment = applicationEnvironment {

568

config = HoconApplicationConfig(ConfigFactory.load())

569

configure(config)

570

}

571

572

// API server

573

val apiServer = embeddedServer(Netty, sharedEnvironment) {

574

connector {

575

port = 8080

576

host = "0.0.0.0"

577

}

578

}

579

580

// Admin server

581

val adminServer = embeddedServer(CIO, sharedEnvironment) {

582

connector {

583

port = 8081

584

host = "127.0.0.1" // Admin interface local only

585

}

586

}

587

588

// Start both servers

589

apiServer.start(wait = false)

590

adminServer.start(wait = false)

591

592

// Keep main thread alive

593

runBlocking {

594

awaitCancellation()

595

}

596

}

597

```

598

599

## Engine-Specific Configuration

600

601

### Netty Configuration

602

603

```kotlin { .api }

604

embeddedServer(Netty, port = 8080) {

605

// Netty-specific settings

606

connectionGroupSize = 2 // Boss threads

607

workerGroupSize = 8 // Worker threads

608

callGroupSize = 16 // Call handler threads

609

610

shutdownGracePeriod = 2000

611

shutdownTimeout = 5000

612

613

// Request timeout configuration

614

requestQueueLimit = 16

615

runningLimit = 32

616

617

// TCP configuration

618

tcpKeepAlive = true

619

reuseAddress = true

620

621

connector {

622

port = 8080

623

host = "0.0.0.0"

624

}

625

}

626

```

627

628

### CIO Configuration

629

630

```kotlin { .api }

631

embeddedServer(CIO, port = 8080) {

632

// CIO-specific settings

633

connectionGroupSize = 1

634

workerGroupSize = availableProcessors()

635

callGroupSize = availableProcessors() * 2

636

637

connectionIdleTimeout = 45000

638

639

connector {

640

port = 8080

641

host = "0.0.0.0"

642

}

643

}

644

```

645

646

This comprehensive documentation covers all aspects of Ktor's server engine system, from basic embedded server creation to advanced production deployment configurations.