The Pronghorn HTTP Server is a low-level, high performance HTTP server written in Kotlin. It utilizes the Pronghorn Coroutine Framework to fully utilize available system resources with minimal overhead. No external dependencies are required, however, functionality can be enhanced through optional plugins which may contain external dependencies.
Note: The Pronghorn HTTP Server is early in development, and is in many ways a testbed for the Pronghorn Coroutine Framework. As such it is not currently recommended in production environments. Documentation will improve as it matures.
Pronghorn is best suited for applications where high throughput and/or low latency with minimal cpu overhead are critical requirements.
The following is the simple Hello World server example using Pronghorn.
fun main(args: Array<String>) {
val helloWorldResponse = HttpResponses.OK("Hello, World!", CommonContentTypes.TextPlain)
val helloWorldHandler = StaticHttpRequestHandler(helloWorldResponse)
val server = HttpServer("localhost", 8080)
server.registerUrlHandler("/hello", helloWorldHandler)
server.start()
}
Alternatively to the above, The HttpServer class can be constructed with an instance of HttpServerConfig
val config = HttpServerConfig(address = ..., ...)
val server = HttpServer(config)
- address - The address to bind to.
- workerCount - The number of worker threads to utilize, should likely be the number of cores available (default: number of logical cpu cores)
- sendServerHeader - If true, the Server header is automatically sent with each response (default: true)
- sendDateHeader - If true, the Date header is automatically sent with each response (default: true)
- serverName - The value to send in the Server response header if sendServerHeader is true (default: "Pronghorn")
- reusableBufferSize - The size of pooled read/write buffers, should be at least as large as the average expected request (default: 64 KiB)
- reusePort - If true, the SO_REUSEPORT socket option is used and each worker uses a dedicated socket (default: auto-detected)
- listenBacklog - The value for the accept queue for the server socket (default: 128)
- acceptGrouping - How many connections should be accepted in a batch, usually equal to the listen backlog (default: 128)
- maxPipelinedRequests - The maximum number of http requests allowed to be pipelined on a single connection (default: 64)
- maxRequestSize - The maximum acceptable size of a single http request (default: 1 MiB)
- useDirectByteBuffers - Whether socket read/write buffers should be direct ByteBuffers (default: true)
Pronghorn ships with three optional plugins
Utilizes the popular SLF4J library for logging. See https://www.slf4j.org/manual.html for more information.
This plugin offers high performance alternatives for collection types used at critical points throughout Pronghorn. The excellent JCTools library provides wait free and lock less implementations of many concurrent data structures. Utilizing these in place of Java standard library collections results in performance improvements for some workloads.
This plugin utilizes the OpenHFT Zero Allocation Hashing library to provide high performance hashing ByteArrays. This improves Pronghorn performance under some workloads and configurations.
There are two ways to configure Pronghorn to utilize a plugin implementation.
By default Pronghorn looks for a resource file named "pronghorn.properties" in Java properties file format. The keys of this file should be the Plugin class for which an implementation is being specified, with the value being the implementation.
For example, if all of the above plugin dependencies have been included, the pronghorn.properties file would appear as:
pronghorn.plugins.LoggingPlugin = tech.pronghorn.plugins.Slf4jLoggingPlugin
pronghorn.plugins.SpscQueuePlugin = tech.pronghorn.plugins.JCToolsSpscQueuePlugin
pronghorn.plugins.MpscQueuePlugin = tech.pronghorn.plugins.JCToolsMpscQueuePlugin
pronghorn.plugins.ConcurrentMapPlugin = tech.pronghorn.plugins.JCToolsConcurrentMapPlugin
pronghorn.plugins.ConcurrentSetPlugin = tech.pronghorn.plugins.JCToolsConcurrentSetPlugin
pronghorn.plugins.ArrayHasherPlugin = tech.pronghorn.plugins.OpenHFTArrayHasherPlugin
Alternatively, plugins can be configured programmatically utilizing the setPlugin method as in this example:
LoggingPlugin.setPlugin(Slf4jLoggingPlugin)
Copyright 2017 Pronghorn Technology LLC
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.