Skip to content

Commit

Permalink
Make # of connections accepted per event loop cycle configurable, and…
Browse files Browse the repository at this point in the history
… raise the default (#3186)

Per @weissi's suggestion, make the number of connections accepted per event loop tick configurable.
  • Loading branch information
gwynne committed May 4, 2024
1 parent b1057fe commit af86ea4
Showing 1 changed file with 23 additions and 6 deletions.
29 changes: 23 additions & 6 deletions Sources/Vapor/HTTP/Server/HTTPServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ public final class HTTPServer: Server, Sendable {
/// This is the same as `NIOSSLCustomVerificationCallback` but just marked as `Sendable`
@preconcurrency
public var customCertificateVerifyCallback: (@Sendable ([NIOSSLCertificate], EventLoopPromise<NIOSSLVerificationResult>) -> Void)?

/// The number of incoming TCP connections to accept per "tick" (i.e. each time through the server's event loop).
///
/// Most users will never need to change this value; its primary use case is to work around benchmarking
/// artifacts where bursts of connections are created within extremely small intervals. See
/// https://forums.swift.org/t/standard-vapor-website-drops-1-5-of-requests-even-at-concurrency-of-100/71583/49
/// for additional information.
public var connectionsPerServerTick: UInt

public init(
hostname: String = Self.defaultHostname,
Expand All @@ -186,7 +194,9 @@ public final class HTTPServer: Server, Sendable {
serverName: String? = nil,
reportMetrics: Bool = true,
logger: Logger? = nil,
shutdownTimeout: TimeAmount = .seconds(10)
shutdownTimeout: TimeAmount = .seconds(10),
customCertificateVerifyCallback: (@Sendable ([NIOSSLCertificate], EventLoopPromise<NIOSSLVerificationResult>) -> Void)? = nil,
connectionsPerServerTick: UInt = 256
) {
self.init(
address: .hostname(hostname, port: port),
Expand All @@ -201,10 +211,12 @@ public final class HTTPServer: Server, Sendable {
serverName: serverName,
reportMetrics: reportMetrics,
logger: logger,
shutdownTimeout: shutdownTimeout
shutdownTimeout: shutdownTimeout,
customCertificateVerifyCallback: customCertificateVerifyCallback,
connectionsPerServerTick: connectionsPerServerTick
)
}

public init(
address: BindAddress,
backlog: Int = 256,
Expand All @@ -218,7 +230,9 @@ public final class HTTPServer: Server, Sendable {
serverName: String? = nil,
reportMetrics: Bool = true,
logger: Logger? = nil,
shutdownTimeout: TimeAmount = .seconds(10)
shutdownTimeout: TimeAmount = .seconds(10),
customCertificateVerifyCallback: (@Sendable ([NIOSSLCertificate], EventLoopPromise<NIOSSLVerificationResult>) -> Void)? = nil,
connectionsPerServerTick: UInt = 256
) {
self.address = address
self.backlog = backlog
Expand All @@ -237,7 +251,8 @@ public final class HTTPServer: Server, Sendable {
self.reportMetrics = reportMetrics
self.logger = logger ?? Logger(label: "codes.vapor.http-server")
self.shutdownTimeout = shutdownTimeout
self.customCertificateVerifyCallback = nil
self.customCertificateVerifyCallback = customCertificateVerifyCallback
self.connectionsPerServerTick = connectionsPerServerTick
}
}

Expand Down Expand Up @@ -269,6 +284,7 @@ public final class HTTPServer: Server, Sendable {
let canBeUpdatedDynamically =
oldValue.address == newValue.address
&& oldValue.backlog == newValue.backlog
&& oldValue.connectionsPerServerTick == newValue.connectionsPerServerTick
&& oldValue.reuseAddress == newValue.reuseAddress
&& oldValue.tcpNoDelay == newValue.tcpNoDelay

Expand Down Expand Up @@ -388,7 +404,8 @@ private final class HTTPServerConnection: Sendable {
) -> EventLoopFuture<HTTPServerConnection> {
let quiesce = ServerQuiescingHelper(group: eventLoopGroup)
let bootstrap = ServerBootstrap(group: eventLoopGroup)
/// Specify backlog and enable `SO_REUSEADDR` for the server itself.
/// Specify accepts per loop and backlog, and enable `SO_REUSEADDR` for the server itself.
.serverChannelOption(ChannelOptions.maxMessagesPerRead, value: configuration.connectionsPerServerTick)
.serverChannelOption(ChannelOptions.backlog, value: Int32(configuration.backlog))
.serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: configuration.reuseAddress ? SocketOptionValue(1) : SocketOptionValue(0))

Expand Down

0 comments on commit af86ea4

Please sign in to comment.