0
# Server Engines and Embedded Servers
1
2
Application engine abstraction and embedded server functionality for hosting Ktor applications. Provides pluggable server engines with unified configuration and lifecycle management.
3
4
## Capabilities
5
6
### Application Engine Interface
7
8
Core interface for all server engines that can host Ktor applications.
9
10
```kotlin { .api }
11
/**
12
* An engine which runs an application
13
*/
14
interface ApplicationEngine {
15
/** Application environment configuration */
16
val environment: ApplicationEnvironment
17
18
/** Get resolved connector configurations for this engine */
19
suspend fun resolvedConnectors(): List<EngineConnectorConfig>
20
21
/** Start the engine, optionally wait for completion */
22
fun start(wait: Boolean = false): ApplicationEngine
23
24
/** Start the engine in suspending fashion */
25
suspend fun startSuspend(wait: Boolean = false): ApplicationEngine
26
27
/** Stop the engine with configurable grace and timeout periods */
28
fun stop(gracePeriodMillis: Long = 500, timeoutMillis: Long = 500)
29
}
30
```
31
32
### Engine Configuration
33
34
Configuration classes for customizing engine behavior and performance characteristics.
35
36
```kotlin { .api }
37
/**
38
* Configuration for ApplicationEngine instances
39
*/
40
open class ApplicationEngine.Configuration {
41
/** Number of parallel processing threads */
42
val parallelism: Int
43
44
/** Size of connection group thread pool */
45
var connectionGroupSize: Int
46
47
/** Size of worker group thread pool */
48
var workerGroupSize: Int
49
50
/** Size of call processing thread pool */
51
var callGroupSize: Int
52
53
/** Grace period for shutdown in milliseconds */
54
var shutdownGracePeriod: Long
55
56
/** Timeout for shutdown in milliseconds */
57
var shutdownTimeout: Long
58
59
/** List of connector configurations */
60
var connectors: MutableList<EngineConnectorConfig>
61
}
62
```
63
64
### Base Engine Implementation
65
66
Abstract base class providing common engine functionality.
67
68
```kotlin { .api }
69
/**
70
* Base class for implementing ApplicationEngine
71
*/
72
abstract class BaseApplicationEngine : ApplicationEngine {
73
/** Application environment */
74
val environment: ApplicationEnvironment
75
76
/** Engine-specific processing pipeline */
77
val pipeline: EnginePipeline
78
79
/** Monitor for engine events */
80
val monitor: Events
81
82
/** Application instance hosted by this engine */
83
val application: Application
84
}
85
```
86
87
### Embedded Server
88
89
High-level embedded server functionality for easy application hosting.
90
91
```kotlin { .api }
92
/**
93
* Represents an embedded server that hosts an application
94
*/
95
class EmbeddedServer<TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> {
96
/** Event monitor for server lifecycle events */
97
val monitor: Events
98
99
/** Application environment */
100
val environment: ApplicationEnvironment
101
102
/** Hosted application instance */
103
val application: Application
104
105
/** Underlying engine instance */
106
val engine: TEngine
107
}
108
```
109
110
### Engine Factory Interface
111
112
Factory interface for creating ApplicationEngine instances with specific configurations.
113
114
```kotlin { .api }
115
/**
116
* Factory interface for creating ApplicationEngine instances
117
*/
118
interface ApplicationEngineFactory<TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> {
119
/** Create configuration instance */
120
fun configuration(configure: TConfiguration.() -> Unit = {}): TConfiguration
121
122
/** Create engine instance */
123
fun create(
124
environment: ApplicationEnvironment,
125
monitor: Events,
126
developmentMode: Boolean,
127
configuration: TConfiguration,
128
applicationProvider: () -> Application
129
): TEngine
130
}
131
```
132
133
### Embedded Server Factory Functions
134
135
Factory functions for creating embedded server instances with various configuration options.
136
137
```kotlin { .api }
138
/**
139
* Create embedded server with basic configuration
140
*/
141
fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration>
142
embeddedServer(
143
factory: ApplicationEngineFactory<TEngine, TConfiguration>,
144
port: Int = 80,
145
host: String = "0.0.0.0",
146
watchPaths: List<String> = emptyList(),
147
configure: TConfiguration.() -> Unit = {},
148
module: Application.() -> Unit
149
): EmbeddedServer<TEngine, TConfiguration>
150
151
/**
152
* Create embedded server with connector configuration
153
*/
154
fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration>
155
embeddedServer(
156
factory: ApplicationEngineFactory<TEngine, TConfiguration>,
157
connectors: List<EngineConnectorConfig>,
158
watchPaths: List<String> = emptyList(),
159
parentCoroutineContext: CoroutineContext = EmptyCoroutineContext,
160
configure: TConfiguration.() -> Unit = {},
161
module: Application.() -> Unit = {}
162
): EmbeddedServer<TEngine, TConfiguration>
163
164
/**
165
* Create embedded server with custom environment
166
*/
167
fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration>
168
embeddedServer(
169
factory: ApplicationEngineFactory<TEngine, TConfiguration>,
170
environment: ApplicationEnvironment,
171
configure: TConfiguration.() -> Unit = {},
172
module: Application.() -> Unit = {}
173
): EmbeddedServer<TEngine, TConfiguration>
174
175
/**
176
* Create embedded server with ServerConfig
177
*/
178
fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration>
179
embeddedServer(
180
factory: ApplicationEngineFactory<TEngine, TConfiguration>,
181
rootConfig: ServerConfig,
182
configure: TConfiguration.() -> Unit = {}
183
): EmbeddedServer<TEngine, TConfiguration>
184
```
185
186
## Usage Examples
187
188
### Basic Embedded Server
189
190
```kotlin
191
import io.ktor.server.application.*
192
import io.ktor.server.engine.*
193
import io.ktor.server.response.*
194
import io.ktor.server.routing.*
195
196
fun main() {
197
embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
198
routing {
199
get("/") {
200
call.respondText("Hello, World!")
201
}
202
}
203
}.start(wait = true)
204
}
205
```
206
207
### Embedded Server with Custom Configuration
208
209
```kotlin
210
import io.ktor.server.application.*
211
import io.ktor.server.engine.*
212
import io.ktor.server.netty.*
213
214
fun main() {
215
embeddedServer(Netty, port = 8080) {
216
// Engine-specific configuration
217
connectionGroupSize = 2
218
workerGroupSize = 5
219
callGroupSize = 10
220
shutdownGracePeriod = 2000
221
shutdownTimeout = 5000
222
223
// Application configuration
224
}.apply {
225
// Configure application modules
226
application.module {
227
configureRouting()
228
configurePlugins()
229
}
230
}.start(wait = true)
231
}
232
233
fun Application.configureRouting() {
234
routing {
235
get("/health") {
236
call.respondText("OK")
237
}
238
}
239
}
240
241
fun Application.configurePlugins() {
242
install(CallLogging)
243
}
244
```
245
246
### Multiple Connectors
247
248
```kotlin
249
import io.ktor.server.application.*
250
import io.ktor.server.engine.*
251
252
fun main() {
253
val httpConnector = EngineConnectorBuilder().apply {
254
port = 8080
255
host = "0.0.0.0"
256
}
257
258
val httpsConnector = EngineConnectorBuilder().apply {
259
port = 8443
260
host = "0.0.0.0"
261
// SSL configuration would go here
262
}
263
264
embeddedServer(
265
factory = Netty,
266
connectors = listOf(httpConnector, httpsConnector)
267
) {
268
routing {
269
get("/") {
270
call.respondText("Available on both HTTP and HTTPS")
271
}
272
}
273
}.start(wait = true)
274
}
275
```
276
277
### Custom Environment and Configuration
278
279
```kotlin
280
import io.ktor.server.application.*
281
import io.ktor.server.config.*
282
import io.ktor.server.engine.*
283
284
fun main() {
285
// Create custom configuration
286
val config = MapApplicationConfig().apply {
287
put("app.name", "MyKtorApp")
288
put("app.version", "1.0.0")
289
put("server.features.compression", "true")
290
put("database.url", "jdbc:postgresql://localhost/myapp")
291
}
292
293
// Create custom environment
294
val environment = createApplicationEnvironment {
295
this.config = config
296
this.log = LoggerFactory.getLogger("MyKtorApp")
297
}
298
299
embeddedServer(Netty, environment = environment) {
300
// Configure based on custom environment
301
val appName = environment.config.property("app.name").getString()
302
val version = environment.config.property("app.version").getString()
303
304
routing {
305
get("/info") {
306
call.respondText("$appName v$version")
307
}
308
}
309
}.start(wait = true)
310
}
311
```
312
313
### Development Server with Auto-Reload
314
315
```kotlin
316
import io.ktor.server.application.*
317
import io.ktor.server.engine.*
318
319
fun main() {
320
embeddedServer(
321
factory = Netty,
322
port = 8080,
323
host = "0.0.0.0",
324
watchPaths = listOf("classes", "resources"), // Auto-reload on changes
325
configure = {
326
// Development-specific engine settings
327
connectionGroupSize = 1
328
workerGroupSize = 1
329
callGroupSize = 1
330
}
331
) {
332
configureForDevelopment()
333
}.start(wait = true)
334
}
335
336
fun Application.configureForDevelopment() {
337
// Development mode enables additional features
338
val isDevelopment = environment.developmentMode
339
340
if (isDevelopment) {
341
install(CallLogging) {
342
level = Level.DEBUG
343
}
344
345
install(CORS) {
346
allowMethod(HttpMethod.Options)
347
allowMethod(HttpMethod.Put)
348
allowMethod(HttpMethod.Delete)
349
allowMethod(HttpMethod.Patch)
350
allowHeader(HttpHeaders.Authorization)
351
allowCredentials = true
352
anyHost() // Don't do this in production!
353
}
354
}
355
356
routing {
357
get("/dev-info") {
358
if (isDevelopment) {
359
call.respond(mapOf(
360
"development" to true,
361
"autoReload" to true,
362
"javaVersion" to System.getProperty("java.version")
363
))
364
} else {
365
call.respond(HttpStatusCode.NotFound)
366
}
367
}
368
}
369
}
370
```
371
372
### Server Configuration with ServerConfig
373
374
```kotlin
375
import io.ktor.server.application.*
376
import io.ktor.server.engine.*
377
378
fun main() {
379
val serverConfig = serverConfig {
380
developmentMode = false
381
rootPath = "/api/v1"
382
383
// Configure application modules
384
module {
385
configureAuthentication()
386
configureRouting()
387
configurePlugins()
388
}
389
390
module {
391
configureDatabase()
392
}
393
394
// Watch paths for development
395
watchPaths = listOf("build/classes")
396
}
397
398
embeddedServer(Netty, rootConfig = serverConfig) {
399
// Additional engine configuration
400
shutdownGracePeriod = 3000
401
shutdownTimeout = 10000
402
}.start(wait = true)
403
}
404
405
fun Application.configureAuthentication() {
406
install(Authentication) {
407
jwt("auth-jwt") {
408
realm = "ktor app"
409
verifier(makeJwtVerifier())
410
validate { credential ->
411
if (credential.payload.getClaim("username").asString() != "") {
412
JWTPrincipal(credential.payload)
413
} else {
414
null
415
}
416
}
417
}
418
}
419
}
420
```
421
422
### Graceful Shutdown Handling
423
424
```kotlin
425
import io.ktor.server.application.*
426
import io.ktor.server.engine.*
427
import kotlinx.coroutines.*
428
429
fun main() {
430
val server = embeddedServer(Netty, port = 8080) {
431
routing {
432
get("/") {
433
call.respondText("Hello, World!")
434
}
435
}
436
}
437
438
// Handle shutdown gracefully
439
Runtime.getRuntime().addShutdownHook(Thread {
440
println("Shutting down server...")
441
server.stop(
442
gracePeriodMillis = 5000,
443
timeoutMillis = 10000
444
)
445
println("Server stopped")
446
})
447
448
server.start(wait = true)
449
}
450
```
451
452
### Custom Engine Factory
453
454
```kotlin
455
import io.ktor.server.application.*
456
import io.ktor.server.engine.*
457
458
// Custom engine factory wrapper
459
class CustomEngineFactory<TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration>(
460
private val delegate: ApplicationEngineFactory<TEngine, TConfiguration>
461
) : ApplicationEngineFactory<TEngine, TConfiguration> {
462
463
override fun configuration(configure: TConfiguration.() -> Unit): TConfiguration {
464
return delegate.configuration {
465
// Apply default configuration
466
shutdownGracePeriod = 5000
467
shutdownTimeout = 10000
468
configure()
469
}
470
}
471
472
override fun create(
473
environment: ApplicationEnvironment,
474
monitor: Events,
475
developmentMode: Boolean,
476
configuration: TConfiguration,
477
applicationProvider: () -> Application
478
): TEngine {
479
// Add custom monitoring
480
monitor.subscribe(ServerReady) { server ->
481
println("Custom server started: ${server.environment.config}")
482
}
483
484
return delegate.create(environment, monitor, developmentMode, configuration, applicationProvider)
485
}
486
}
487
488
fun main() {
489
val customNetty = CustomEngineFactory(Netty)
490
491
embeddedServer(customNetty, port = 8080) {
492
routing {
493
get("/") {
494
call.respondText("Custom engine!")
495
}
496
}
497
}.start(wait = true)
498
}
499
```