The pixl-ipc module provides interprocess communication (IPC) using unix domain sockets to provide fast local communication between processes that avoids touching the network stack. It is built as a component of pixl-server, a lightweight framework for building node.js daemon applications.
- JSON messages over UNIX domain sockets
- Protocol is language agnostic
- PHP and Node.js client classes provided
- Node.js client now supports async/await
var PixlServer = require('pixl-server');
var server = new PixlServer({
__name: 'MyIPCServer',
__version: "0.1",
config: {
"log_dir": "/var/tmp",
"log_filename": "my_ipc_test.log",
"debug_level": 9,
"IPCServer" : {
"socket_path" : "/var/tmp/my_ipc_server.sock"
}
},
components: [require('pixl-ipc')]
});
server.startup( function() {
console.log("Main startup");
server.IPCServer.addURIHandler(/^\/myapi\/test/, "IPCServer", function(request, callback) {
callback({"hello":"thanks for your message"});
});
} );
The Node.js client supports callback style requests as well as async/await-style Promises. If a callback is omitted, the methods connect/send/close will return a promise.
const IPCClient = require('pixl-ipc/client');
var testClient = new IPCClient("/var/tmp/my_ipc_server.sock");
testClient.connect(function() {
testClient.send('/myapi/test', {"welcome":42}, function(err, data) {
console.log(err, data);
});
testClient.send('/ipcserver/test/echo', {"ping":"me"}, function(err, data) {
console.log(err, data);
});
});
// Or using async/await
async function run() {
let asyncClient = new IPCClient("/var/tmp/my_ipc_server.sock");
try {
await asyncClient.connect();
let result = await asyncClient.send('/myapi/test', {"welcome":42});
console.log(result);
await.asyncClient.close();
}
catch (e) {
console.log("Exception: " + e);
}
}
run();
Name | Type | Description |
---|---|---|
socket_path | string | Path where the socket file will be created -- must be same in client |
exit_timeout | integer | When shutting down and waiting for client connections to close, this will force an exit when the timeout is exceeded (default 2000ms) |
socket_chmod | string | The CHMOD(2) permission of the socket file (default: '777') |
log_stats_interval | string | The frequency to log various stats using pixl-server event intervals. (default: 'minute') |
Name | Type | Description |
---|---|---|
uriPattern | string or regex | Identifies the type of messages the handler should receive by matching the URI request pattern |
name | string | The name to associate with the handler (for logging) |
callback | function | The method to call when a message is received |
This method registers callback handler to process incoming requests matching the specified URI pattern. When the handler is called it is passed the request object and response callback.
The request contains:
Name | Type | Description |
---|---|---|
uri | string | URI passed from client |
data | json object | The data from the client |
pid | integer | The process ID of the client (Not yet implemented) |
myHandler(request, callback) {
console.dir(request);
callback({thanks: "a lot"});
}
Returns various statistics about the IPC server.
You can pass in any arbitrary object and the server will echo back the message in the response
Name | Type | Description |
---|---|---|
delay | integer | The time in milliseconds to delay before sending a response back |
This sets a delay response to the caller and sends back {delay: N}.
Name | Type | Description |
---|---|---|
socket_path | string | Path where the socket file will be created -- must be same in client |
logger | PixlLogger | Instance of a PixlLogger object if you want logging (optional) |
options | json object | Override settings such as request timeout |
// options with current defaults, times are in milliseconds
{
userAgent: "Node/IPCClient" + process.cwd(), // A string that identifies your application
requestTimeout : 10*1000, // How long to wait before timing out the request
autoReconnect: 1000, // Reconnect in N ms if the connection is broken or set to 0 to prevent automatic reconnect
codeToErr: false, // When a result message contains a non-falsey (zero) "code" element use the message as the error in callback
messageTransform: null, // Provide a function to transform the error or data result before sending to the callback (details below)
logStatsInterval: null // Logs perf metrics of the JSON stream every logStatsInterval milliseconds
}
Creates the client object and overrides default options if provided.
For messageTransform you can provide a function that alters the error or data before it is sent to the messages callback handler. It will override the codeToErr option if provided. The function is passed the full message object and should return an array of [err, data]. Here's an example implementation (the code used to implement codeToErr):
function codeToErr(msg) {
var err = null;
if (msg.code) {
err = msg;
}
else if (msg.data && msg.data.code) {
err = msg.data;
}
return [err, msg.data];
}
Name | Type | Description |
---|---|---|
callback | function | The function to call once the client is connected to the server |
Opens a socket connection to the server. Callback is invoked with an error object or null if there was no error.
Name | Type | Description |
---|---|---|
uri | string | The server URI being requested |
message | json object | The data to send to the IPC server |
callback | function | When the server sends a response, this callback will be invoked with (err, data) |
Sends an asynchronous JSON request to the IPC Server and gets the response back in the callback.
Name | Type | Description |
---|---|---|
callback | function | Called once the connection is closed (optional) |
Closes the socket connection and clears any timers.
PixlIPCClient provides an API for sending socket messages to the IPC server. Unlike the Node client, it is a blocking, synchronous model.
Sample
require_once "PixlIPCClient.class.php";
$ipc = new PixlIPCClient("/tmp/node_ipc_server.sock");
$ipc->connect();
$msg = array("hello"=>"there");
$result = $ipc->send('/ipcserver/test/echo', $msg);
print($msg)
Name | Type | Description |
---|---|---|
socket_path | string | Path where the socket file will be created -- must be same in client |
options | hash array | Override settings such as request timeout |
// options with current defaults, times are in milliseconds
array(
'userAgent' => "PHP/PixlIPCClient" . getcwd(), // A string that identifies your application
'requestTimeout' => 500, // How long to wait before timing out the request
'connectTimeout' => 500 // How long to wait before timing out the connection
)
Creates the client object and overrides default options if provide.
Opens a socket connection to the server. Throws exception if there was an error.
Name | Type | Description |
---|---|---|
uri | string | The server URI being requested |
message | hash array | The data to send to the IPC server |
Sends a JSON request to the IPC Server and returns the response. Throws exception if there was an error.
In testing on a local ancient laptop (2011 2.4 GHz Intel Core i7), performance is sub-millisecond for message sizes under about 20K and about twice as fast on a reasonable AWS EC2 Instance (m4.xlarge).
Msg Size | laptop (ms) | EC2 (ms) |
---|---|---|
1K | 0.13 | 0.09 |
5K | 0.19 | 0.094 |
10K | 0.36 | 0.18 |
20K | 0.64 | 0.316 |
100K | 3.35 | 1.374 |