NodNod is a websocket server that can stream node stats to any websocket client. NodNod can be deployed as single or multinode cluster.
In case of multinode cluster deployment, the NodNod cluster is masterless, so each NodNod server should stream stats for all connected/live NodNod peers in the cluster straight to the client.
Assuming you already have a cluster composed of mutliple servers. Start by installing and running NodNod on each server with configuration file specifying all other NodNod peers (see Config file).
Once a NodNod starts, it will start connecting to other peers via a websocket connection. The reason behind establishing those connections; is that NodNod aims at constructing a masterless stats collector cluster. So, any NodNod server can stream stats for the whole cluster instead of just a single node.
This setup also eliminates the need of a master/controller node, allowing loadbalanced setup while serving large number of clients.
Please check the Tutorial section to see NodNod in action.
go get github.com/mohabusama/nodnod
For running tests
go test ./...
NodNod is using Gorilla Websocket for websocket server implementation and gopsutil for stats collecting. Current collected stats are:
- CPUUsage
- Total Disk
- Used Disk
- Used Disk percentage
- Total Memory
- Used Memory
- Used Memory percentage
NodNod uses JSON requests over websocket connections. The request sent to NodNod server should include the following fields:
- type: Integer represents the type of the request.
- 0: stat connected node only.
- 1: stat all cluster nodes.
- statType: Integer represents the type of stats requested.
- 0: ALL stats. Granular stats is not supported yet.
Sample request:
{
"type": 1,
"statType": 0
}
Response will hold the following fields:
- host: The connected host name.
- nodes: Collected node(s) stats.
- error: Error string if any. Empty string means no error happened.
Example response:
{
"host": "kyle",
"nodes": {
"kyle": {
"name": "kyle",
"cpuUsed": 5,
"diskTotal": 249769419776,
"diskUsed": 66792268800,
"diskUsedPercent": 26.741571830491146,
"memoryTotal": 8589934592,
"memoryUsed": 5699850240,
"memoryUsedPercent": 66.35499000549316,
"error": ""
}
},
"error": ""
}
A NodNod server requires a config file to start.
The config file is a json
file which describes the existing NodNod nodes/peers in the cluster.
{
"nodes": [
"192.168.20.15",
"192.168.20.16",
"192.168.20.17"
],
"mode": "pull"
}
Start NodNod server by passing config
file path, listen
address in the form "<ip>:<port>"
and a name
which will identify this NodNod server within the cluster (the default name
is the hostname).
Usage: nodnod [OPTIONS]
OPTIONS:
-config string
Path to configuration path. (default "./conf/conf.json")
-debug
Set logging level to DEBUG!
-help
Print help!
-listen string
Websocket service listen address (default "127.0.0.1:7070")
-name string
Name of this NodNod server. Default is Host name.
-version
Show version!
The client package can be used to connect and stat a NodNod cluster.
import "github.com/mohabusama/nodnod/client"
Please check nodnod_client.go example to see the client usage.
The _examples
directory includes scripts that could be used to illustrate interaction with a NodNod server.
- nodnod_client.go: Uses the client package to stat a NodNod cluster.
- nodnod_dial.go: Connects to NodNod server, and continously requests server stats with the specified duration. Uses raw Gorilla websocket.
- nodnod_concurrent.go: Runs a concurrency test against a NodNod server/cluster. Uses raw Gorilla websocket.
First, create a sample config.json
file. Here, we will run a cluster of two nodes.
{
"nodes": [
"127.0.0.1:7070",
"127.0.0.1:7071"
],
"mode": "pull"
}
Second, start the first server
$ nodnod --listen 127.0.0.1:7070 --config <path-to-config.json> --name cartman
INFO[0000] Starting NodNod websocket server: [cartman : 127.0.0.1:7070]
INFO[0000] Starting discovery service
WARN[0000] Failed to connect to node: 127.0.0.1:7071. Error: dial tcp 127.0.0.1:7071: getsockopt: connection refused
INFO[0000] Accepted connection with client: 127.0.0.1:63161
INFO[0005] Established connection with node: 127.0.0.1:7071
INFO[0005] Connected to node: [kenny : 127.0.0.1:7071]
In another terminal, start the second server
$ nodnod --listen 127.0.0.1:7071 --config <path-to-config.json> --name kenny
INFO[0000] Starting NodNod websocket server: [kenny : 127.0.0.1:7071]
INFO[0000] Starting discovery service
INFO[0000] Established connection with node: 127.0.0.1:7070
INFO[0000] Connected to node: [cartman : 127.0.0.1:7070]
INFO[0004] Accepted connection with client: 127.0.0.1:63162
The next step is to run one of the _examples
scripts
$ go run nodnod_dial.go
INFO[0000] Received response from node: cartman
INFO[0000] Duration:27.499909ms
{
"host": "cartman",
"nodes": {
"cartman": {
"name": "cartman",
"cpuUsed": 5,
"diskTotal": 249769419776,
"diskUsed": 66792268800,
"diskUsedPercent": 26.741571830491146,
"memoryTotal": 8589934592,
"memoryUsed": 5699850240,
"memoryUsedPercent": 66.35499000549316,
"error": ""
},
"kenny": {
"name": "kenny",
"cpuUsed": 9.090909090909092,
"diskTotal": 249769419776,
"diskUsed": 66792268800,
"diskUsedPercent": 26.741571830491146,
"memoryTotal": 8589934592,
"memoryUsed": 5700075520,
"memoryUsedPercent": 66.35761260986328,
"error": ""
}
},
"error": ""
}
Or run nodnod_concurrent.go
. Here we will make 200 stats requests, with concurrency of 20 requests, and we are validating returned stats against 2 nodes.
$ go run nodnod_concurrent.go --concurrent 20 --number 200 --nodes 2
INFO[0000] Launched all goroutines!
INFO[0000] Launched all requests!
INFO[0000] In progress ...
INFO[0015] ====SUMMARY====
INFO[0015] Total Duration:3.632180036s
INFO[0015] Total number of requests:200
INFO[0015] Total number of responses:200
INFO[0015] Total number of missing responses:0
INFO[0015] Total number of failed responses:0
INFO[0015] Total number of invalid responses:0
INFO[0015] ========
- Tests
- PUSH mode
- More realistic benchmarking
- Serve static HTML5 demo
The MIT License (MIT)