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. Each 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!
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
andServiceServer
constructors consume native Nodenet.Server
andhttp.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
Socketnaut consists of the following 2 Service concepts.
ServiceProxy
A ServiceProxy
is used in order to bind a TCP server to a specified port (usu. a public port). The ServiceProxy
uniformly distributes TCP connections to ServiceServer
s (e.g., HTTP servers) in the thread pool. The ServiceProxy
manages the thread pool according to the values assigned to the minServers
and maxServers
parameters.
ServiceServer
A ServiceServer
can consume any native Node.js server (e.g., HTTP, HTTPS, TCP). The "wrapped" Node.js server can be used in the same way it would be used natively; it can even be passed into a routing facility.
API
The ServiceProxy Class
socketnaut.ServiceProxy(options)
options
<ServiceProxyOptions>
maxServers
<number>
Optional argument that specifies the maximum number ofServiceServer
threads permitted.minServers
<number>
Optional argument that specifies the minimum number ofServiceServer
threads permitted. Default:0
server
<node:net.Server>
Anet.Server
configured however you choose.serversCheckingInterval
<number>
Optional argument that specifies the approximate interval (milliseconds) at which inactiveServiceServer
s will be cleaned up. Default:30000
workerOptions
<node:worker_threads.WorkerOptions>
OptionalWorkerOptions
passed to theworker_threads.Worker
constructor.
The ServiceServer Class
socketnaut.ServiceServer(options)
options
<ServiceServerOptions>
server
<http.Server>
or<https.Server>
Ahttp.Server
configured however you choose.
Usage
Each Socketnaut Service consists of at least one ServiceProxy
and a respective ServiceServer
. 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 { ServiceProxy } from 'socketnaut';
let hello_world_proxy = new ServiceProxy({
server: net.createServer(),
minServers: 4,
maxServers: 100,
servicesCheckingInterval: 1e6,
serviceURL: require.resolve('./hello_world_http_service.js')
})
hello_world_proxy.server.listen({ port: 3000, host: '0.0.0.0' });
hello_world_http_service.js
import * as http from 'node:http';
import { ServiceServer } from 'socketnaut';
let service = new ServiceServer({
server: http.createServer()
});
service.server.on('request', (req, res) => {
res.end('Hello World!');
});
service.server.listen({ port: 0, host: '127.0.0.1' });
Pass a custom Socketnaut server to Fastify's serverFactory option. (example)
index.js
import * as net from 'node:net';
import { ServiceProxy } from 'socketnaut';
let fastify_proxy = new ServiceProxy({
server: net.createServer(),
minServers: 4,
maxServers: 100,
servicesCheckingInterval: 1e6,
serviceURL: require.resolve('./fastify_http_service.js')
})
fastify_proxy.server.listen({ port: 3010, host: '0.0.0.0' });
fastify_http_service.js
import * as http from 'node:http';
import { ServiceServer } from 'socketnaut';
import Fastify from 'fastify'
const serverFactory = (handler, opts) => {
let service = new ServiceServer({
server: http.createServer((req, res) => {
handler(req, res)
})
});
return service.server;
}
const fastify = Fastify({ serverFactory });
fastify.post('/blocking-request', (req, reply) => {
for (let now = Date.now(), then = now + 100; now < then; now = Date.now());
reply.send({ hello: 'world' });
});
fastify.listen({ port: 0, host: '127.0.0.1' });
Tuning Strategies
Socketnaut scaling can be tuned by specifying a minimum and maximum number of allocated ServiceServer
threads. The minimum and maximum number of ServiceServer
threads can be specified in the constructor of each ServiceProxy
by assigning values to the minServers
and maxServers
parameters. Further, the serversCheckingInterval
can be used in order to set the frequency at which ServiceServer
s are culled until the minServers
threshold is reached.
ServiceProxy
constructor parameters relevant to tuning:
socketnaut.ServiceProxy(options)
- options
<ServiceProxyOptions>
minServers
<number>
An argument that specifies the minimum number ofServiceServer
threads permitted.maxServers
<number>
An argument that specifies the maximum number ofServiceServer
threads permitted.serversCheckingInterval
<number>
An argument that specifies the approximate interval at which inactiveServiceServer
s will be cleaned up. Default:30000
The minServers
argument specifies the minimum number of Worker threads permitted. minServers
threads will be instantiated when the Socketnaut Server starts. Socketnaut will not allow the thread pool to drop below the specified threshold.
The maxServers
argument is a hard limit.
The serversCheckingInterval
specifies the approximate interval at which Socketnaut will attempt to clean up inactive 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 close its server and exit. The default interval is 30000
milliseconds.
By variously specifying minServers
, maxServers
, serversCheckingInterval
you can tune Socketnaut according to the requirements of your environment.
Logging
Socketnaut uses the Node.js memoir
logging facility. You can set the log level in your index.js
by passing a valid log level argument to the logLevel
parameter of the ServiceProxy
constructor.
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.
How is Socketnaut related to eptanaut?
Socketnaut is an offshoot of the eptanaut project. Socketnaut provides functionality similar to eptanaut; however, it implements a clean separation between the Proxy and Server concepts. Socketnaut can be used in order to easily scale otherwise single threaded Node.js server implementations.