Package Exports
- socketnaut
- socketnaut/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (socketnaut) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Socketnaut
Scalable multithreaded Node.js servers made easy.
Socketnaut makes scaling native Node.js servers (e.g., HTTP, HTTPS, TCP) easy. A Socketnaut Service consists of a TCP Proxy and a pool of HTTP servers. When the server pool is exhausted, Socketnaut will uniformly distribute incoming TCP sockets across the pool of allocated servers. This strategy allows for both distribution and parallel processing of incoming requests. Socketnaut exposes the same API for HTTP requests provided by Node's http.Server
and https.Server
; hence, if you know the Node API, you already know how to build applications on Socketnaut!
Socketnaut can be used in order to scale the main thread of performant Node.js web frameworks (e.g., Fastify).
Features
- Socketnaut requires 0 out-of-org dependencies. Socketnaut's dependencies are published and maintained by the FAR Analytics and Research org.
Dependencies:- The
farar/memoir
logger. - The
farar/port_agent
RPC facility.
- The
- The Socketnaut
ServiceProxy
andServiceAgent
constructors consume native Nodenet.Server
,http.Server
, andhttps.Server
instances; you can configure them however you choose. - The
http.IncomingMessage
andhttp.ServerResponse
objects passed torequest
listeners are unadulterated native Node objects - nothing added - nothing removed. - Import Socketnaut as a Node.js module (see the Hello World! example) or take advantage of the packaged type definitions and import it into your TypeScript project.
Table of Contents
Installation
npm install socketnaut
Concepts
A Socketnaut Service consists of a ServiceProxy
and a ServiceAgent
.
ServiceProxy
A ServiceProxy
is used in order to bind a TCP server to a specified port (usu. a public port). A ServiceProxy
can be instantiated using the createServiceProxy
function. The ServiceProxy
uniformly distributes TCP connections to servers (e.g., HTTP servers) in the Worker thread pool. The ServiceProxy
manages the thread pool according to the values specified for the minWorkers
and maxWorkers
parameters.
ServiceAgent
A ServiceAgent
coordinates its state with its respective Proxy (e.g., Worker scaling and termination). A ServiceAgent
can be instantiated using the createServiceAgent
function. It can consume a native Node.js server (e.g., HTTP, HTTPS, TCP). The "wrapped" Node.js server may be used the same way it is used natively; it can even be passed into an external routing facility or provided to a web application framework; please see the Examples section for instruction on how to do this.
API
The ServiceProxy
Class
socketnaut.createServiceProxy(options)
options
<ServiceProxyOptions>
maxWorkers
<number>
Optional argument that specifies the maximum number ofServiceAgent
Worker threads permitted.minWorkers
<number>
Optional argument that specifies the minimum number ofServiceAgent
Worker threads permitted. Default:0
server
<node:net.Server>
Anet.Server
configured however you choose.workersCheckingInterval
<number>
Optional argument that specifies the approximate interval (milliseconds) at which inactiveServiceAgent
s will be cleaned up. Default:60000
workerOptions
<node:worker_threads.WorkerOptions>
OptionalWorkerOptions
passed to theworker_threads.Worker
constructor.workerURL
<string>
or<URL>
The URL or path to the.js
module file that contains theServiceAgent
instance. This is the module that will be scaled according to the values specified forminWorkers
andmaxWorkers
. Please see the Examples section for how to reference aServiceAgent
module.
Returns:
<socketnaut.ServiceProxy>
Creates a ServiceProxy
. Each process may contain any number of ServiceProxy
s. However, all ServiceProxy
s run in the main thread; hence, the number of instances created in each process should be considered carefully.
The ServiceAgent
Class
socketnaut.createServiceAgent(options)
options
<ServiceAgentOptions>
server
<node:http.Server>
or<node:https.Server>
or<node:net.Server>
A native Node.jsServer
configured however you choose.
Returns:
<socketnaut.ServiceAgent>
Creates a ServiceAgent
. Just one ServiceAgent
may be instantiated for each Worker; hence, this function will throw an Error if it is called more than once.
Usage
Each Socketnaut Service consists of at least one ServiceProxy
and a respective ServiceAgent
. Please see the Examples section for how to create a Socketnaut Service.
Examples
An instance of Hello World! (example)
index.js
import * as net from 'node:net';
import { createServiceProxy } from 'socketnaut';
const proxy = createServiceProxy({
server: net.createServer(),
minWorkers: 42,
maxWorkers: 100,
workersCheckingInterval: 1e6,
workerURL: './http_server.js'
});
proxy.server.listen({ port: 3000, host: '0.0.0.0' });
http_server.js
import * as http from 'node:http';
import { createServiceAgent } from 'socketnaut';
const service = createServiceAgent({
server: http.createServer() // Configure this HTTP server however you choose.
});
service.server.on('request', (req, res) => {
for (let now = Date.now(), then = now + 100; now < then; now = Date.now()); // Block for 100 milliseconds.
res.end('Hello World!');
});
service.server.listen({ port: 0, host: '127.0.0.1' });
// Specifying port 0 here will cause the Server to listen on a random port.
// Socketnaut will communicate the random port number to the ServiceProxy.
Use Socketnaut to scale the main thread of a Fastify server. (example)
Please see the Fastify example for a working implementation.
Use Socketnaut to scale the main thread of an Express server. (example)
Please see the Express example for a working implementation.
Redirect HTTP connections to an HTTPS Service. (example)
Please see the Redirect HTTP to HTTPS example for a working implementation.
Tuning Strategies
Scaling can be tuned by specifying a minimum and maximum number of allocated Worker threads. The minimum and maximum number of Worker threads can be specified in the constructor of each ServiceProxy
by assigning values to the minWorkers
and maxWorkers
parameters. Further, the workersCheckingInterval
can be used in order to set the frequency at which inactive Worker threads are culled until the minWorkers
threshold is reached.
ServiceProxy
constructor parameters relevant to tuning:
socketnaut.createServiceProxy(options)
- options
<ServiceProxyOptions>
minWorkers
<number>
Optional argument that specifies the minimum number ofServiceAgent
Worker threads permitted. Default:0
maxWorkers
<number>
An argument that specifies the maximum number ofServiceAgent
threads permitted.workersCheckingInterval
<number>
An argument that specifies the approximate interval at which inactiveServiceAgent
s will be cleaned up. Default:60000
The minWorkers
argument specifies the minimum number of Worker threads permitted. minWorkers
threads will be instantiated when the Socketnaut Proxy starts. Socketnaut will not allow the thread pool to drop below the specified threshold.
The maxWorkers
argument is a hard limit.
The workersCheckingInterval
specifies the approximate interval at which Socketnaut will attempt to clean up inactive Worker threads. If Socketnaut's Proxy finds that a thread has 0 connections, Socketnaut will remove it from the pool and send it a notification requesting that it exit. The default interval is 60000
milliseconds.
By variously specifying minWorkers
, maxWorkers
, and workersCheckingInterval
you can tune Socketnaut according to the requirements of your environment.
Logging
Socketnaut uses the Node.js memoir
logging facility. You can set Socketnaut's log level in your index.js
by importing the memoir consoleHandler
and setting it's logLevel
to DEBUG
| INFO
| WARN
| ERROR
. The default is INFO
. For example:
index.js
import { consoleHandler, Level } from 'socketnaut';
consoleHandler.setLevel(Level['DEBUG']);
Socketnaut exports its instance of a memoir
logger, named socketlog
, which can be consumed and reconfigured by another memoir
logger; see the memoir
documentation for how to do this - or use the logger of your choice.
FAQ
What kind of scaling implementation is this?
Socketnaut is a multithreaded vertical scaling implementation. However, Socketnaut could be containerized and scaled horizontally.