RPC : Remote Procedure Call
This Rpc
is a Remote procedure call module. This module can implement multi-process calling services using AF_UNIX
type sockets or network remote calling services using UDP
protocol.
The Rpc
of JSRE / EdgerOS is very powerful and is mainly used for application and system service IPC and supports the following features:
- Request and response.
- Subscribe and publish.
- Duplex data streaming (Only for
AF_UNIX
type).
User can use the following code to import the Rpc
module.
var Rpc = require('rpc');
Support
The following shows Rpc
module APIs available for each permissions.
User Mode | Privilege Mode | |
---|---|---|
Rpc.Server | ● | |
server.close | ● | |
server.reply | ● | |
server.reverse | ● | |
server.createReadStream | ● | |
server.createWriteStream | ● | |
Rpc.Client | ● | ● |
client.close | ● | ● |
client.call | ● | ● |
client.callSync | ● | ● |
client.fetch | ● | ● |
client.createReadStream | ● | ● |
client.createWriteStream | ● | ● |
Rpc.MAX_MSG_SIZE | ● | ● |
Rpc Server Class
new Rpc.Server(name[, errCallback[, onlyPrivilege]])
name
{String} RPC service name. Consists of letters, numbers, and underscores, no more than 64 bytes.errCallback
{Function} RPC service I/O error callback. default: undefined.onlyPrivilege
{Boolean} Only privileged tasks to access this RPC service. default: false.- Returns: {Object} RPC server object.
Create an RPC server using AF_UNIX
multi-process communication. Only Privileged Mode supports creating servers.
Example
var server = new Rpc.Server('LocalServer_1');
new Rpc.Server(saddr[, errCallback[, onlyPrivilege]])
saddr
{Object} RPC server socket address.errCallback
{Function} RPC service I/O error callback. default: undefined.onlyPrivilege
{Boolean} Only privileged tasks to access this RPC service. default: false.- Returns: {Object} RPC server object.
Create an RPC server using UDP
protocol. Only Privileged Mode supports creating servers.
Example
var saddr = socket.sockaddr('127.0.0.1', 3000);
var server = new Rpc.Server(saddr);
Rpc Server Object
The RPC server object inherits from EventEmitter
, and the on()
method can be used to add processing callbacks for different services.
server.close()
Close this RPC server. this RPC server object is no longer allowed to be used after closed.
server.reply(msg, to, seq[, timeout])
msg
{Object} Reply object.to
{Object} Reply target.seq
{Integer} Client command sequence number, must be the same as the client request message sequence number.timeout
{Integer} Wait timeout in milliseconds. default: undefined means wait forever.- Returns: {Boolean} Whether to reply message send successfully.
to
object must includes:
addr
{String} | {Object} Client address.
Use the emitterfrom
parameter directly.
Send a server reply to the specified client.
Example
var server = new Rpc.Server('LocalServer_1');
server.on('command_echo', (msg, from, seq) => {
console.log('receive command_echo', msg, from);
server.reply({ res: 'ok', msg }, from, seq);
});
server.on('command_sth', (msg, from, seq) => {
console.log('receive command_sth', msg, from);
server.reply({ res: 'ok' }, from, seq);
});
server.reverse(event, msg, to[, timeout])
event
{String} Client event that you want to trigger.msg
{Object} Reverse message object.to
{Object} Reverse target.timeout
{Integer} Wait timeout in milliseconds. default: undefined means wait forever.- Returns: {Boolean} Whether to reply message send successfully.
to
object must includes:
addr
{String} | {Object} Client address.
Use thefrom
parameter directly.
Send a server asynchronous reverse message to the specified client.
server.createReadStream(clientPid[, alive])
clientPid
{Integer} Specify the allowed client process ID.alive
{Integer} Maximum idle time (ms). default: 30000.- Returns: {ReadStream}
Readable
stream object.
Create a temporary ReadStream
object to receive the data sent by the client. For more information about ReadStream
, please refer to: stream.
alive
is the time to wait for the client WriteStream
to connect. If the client is not connected within this time interval, this ReadStream
will generate a 'Peer timeout!'
error. The minimum time interval is: 1000
.
Example
var server = new Rpc.Server('LocalServer_1');
server.on('to_server', (msg, from, seq) => {
var r = server.createReadStream(from.pid);
var f = fs.createWriteStream('./save.txt');
r.on('error', function(error) {
console.error('Error:', error.message);
f.destroy(error);
});
f.on('finish', function() {
console.log('File save ok!');
});
r.pipe(f);
server.reply({ res: 'ok', id: r.id }, from, seq);
});
server.createWriteStream(rid[, async])
rid
{String} PeerReadStream
id.async
{Boolean} Whether to use pure asynchronous mode, which is less efficient, but fair to other events. default: true.- Returns: {WriteStream}
Writable
stream object.
Create a temporary WriteStream
object to send the data to client. For more information about WriteStream
, please refer to: stream.
Example
var server = new Rpc.Server('LocalServer_1');
server.on('to_client', (msg, from, seq) => {
var s = server.createWriteStream(msg.id);
var f = fs.createReadStream('./save.txt');
s.on('error', function(error) {
console.error('Error:', error.message);
f.destroy(error);
});
s.on('finish', function() {
console.log('File send ok!');
});
f.on('error', function(error) {
console.error('Error:', error.message);
s.destroy(error);
})
f.pipe(s);
server.reply({ res: 'ok' }, from, seq);
});
Rpc Server Events
The RPC server object inherits from EventEmitter
, and the on()
method can be used to add processing callbacks for different services.
Client Command
msg
{Object} Client message.from
{Object} Client information.seq
{Integer} Client command sequence number.
from
object includes:
addr
{String} | {Object} Client address.pid
{Integer} Client process ID.perm
{Integer} Client permission.appid
{Integer} EdgerOS App ID (negative means not EdgerOS App).service
{Boolean} Whether client is a service.signature
{Boolean} Whether has a signature.
Example
server.on('command_echo', (msg, from, seq) => {
console.log('receive command_echo', msg, from);
server.reply({ res: 'ok', msg }, from, seq);
});
Rpc Client Class
new Rpc.Client(name[, errCallback])
name
{String} RPC service name. Consists of letters, numbers, and underscores, no more than 64 bytes.errCallback
{Function} LPC client I/O error callback. default: undefined.- Returns: {Object} RPC client object.
Create an RPC client using AF_UNIX
multi-process communication.
Example
var client = new Rpc.Client('LocalServer_1');
new Rpc.Client(saddr[, errCallback])
saddr
{Object} RPC server socket address.errCallback
{Function} LPC client I/O error callback. default: undefined.- Returns: {Object} RPC client object.
Create an RPC client using UDP
protocol.
Example
var saddr = socket.sockaddr('127.0.0.1', 3000);
var client = new Rpc.Client(saddr);
Rpc Client Object
The RPC client object inherits from EventEmitter
, and the on()
method can be used to listen server reverse events.
client.close()
Close the RPC client, this RPC client object is no longer allowed to be used after closed.
client.call(event, msg[, callback[, timeout]])
event
{String} Server event that you want to trigger.msg
{Object} Call command message.callback
{Function} Server reply callback function.reply
{Object} Server reply message.undefined
indicates that the server response was not received within the specified timeout.
timeout
{Integer} Wait timeout in milliseconds. default: 60000.- Returns: {Boolean} Whether to reply message send successfully.
Send a call request to the server, this function immediately returns after the request is successfully sent. The callback
function is called until the server responds or times out.
Example
var client = new Rpc.Client('LocalServer_1');
client.call('command_echo', { foo: 'foo' }, (reply) => {
console.log('Server reply:', reply);
});
client.callSync(event, msg[, timeout])
event
{String} Server event that you want to trigger.msg
{Object} Call command message.timeout
{Integer} Wait timeout in milliseconds. default: 60000.- Returns: {Object} Server response message.
Send a call request to the server and wait for server reply. If there is no response within the time specified by timeout
, return undefined
.
Example
var client = new Rpc.Client('LocalServer_1');
var reply = client.callSync('command_echo', { foo: 'foo' });
if (reply) {
console.log('Server reply:', reply.msg);
}
client.fetch(event, msg[, timeout])
event
{String} Server event that you want to trigger.msg
{Object} Call command message.timeout
{Integer} Wait timeout in milliseconds. default: 60000.- Returns: {Promise} Promise object.
Send a call request to the server, this function is asynchronous requests and return a Promise
object.
Example
var client = new Rpc.Client('LocalServer_1');
async function echo() {
var reply = await client.fetch('command_echo', { foo: 'bar' });
console.log(reply.msg);
}
client.createReadStream([alive])
alive
{Integer} Maximum idle time (ms). default: 30000.- Returns: {ReadStream}
Readable
stream object.
Create a temporary ReadStream
object to receive the data sent by the server. For more information about ReadStream
, please refer to: stream.
alive
is the time to wait for the client WriteStream
to connect. If the server is not connected within this time interval, this ReadStream
will generate a 'Peer timeout!'
error. The minimum time interval is: 1000
.
Example
var client = new Rpc.Client('LocalServer_1');
var r = client.createReadStream();
client.call('to_client', { id: r.id }, function(reply) {
if (reply && reply.res === 'ok') {
var f = fs.createWriteStream('./xxx.txt');
r.on('error', function(error) {
console.error('Error:', error.message);
f.destroy(error);
});
f.on('finish', function() {
console.log('File save ok!');
});
r.pipe(f);
}
});
client.createWriteStream(rid[, async])
rid
{String} PeerReadStream
id.async
{Boolean} Whether to use pure asynchronous mode, which is less efficient, but fair to other events. default: true.- Returns: {WriteStream}
Writable
stream object.
Create a temporary WriteStream
object to send the data to server. For more information about WriteStream
, please refer to: stream.
Example
var client = new Rpc.Client('LocalServer_1');
client.call('to_server', {}, function(reply) {
if (reply && reply.res === 'ok') {
var s = client.createWriteStream(reply.id);
var f = fs.createReadStream('./xxx.txt');
s.on('error', function(error) {
f.destroy(error);
});
s.on('finish', function() {
console.log('File send ok!');
});
f.pipe(s);
}
});
Rpc Quota
Rpc.MAX_MSG_SIZE
- {Integer}
The maximum length of an RPC single message, usually 16 KBytes.
Example
Here is a typical example of RPC.
- Server
var Rpc = require('rpc');
var iosched = require('iosched');
var server = new Rpc.Server('RemoteProxy');
server.on('dev_on', (msg, from, seq) => {
dev.setOn(msg.dev);
server.reply({ res: 'ok' }, from, seq);
});
server.on('dev_off', (msg, from, seq) => {
dev.setOff(msg.dev);
server.reply({ res: 'ok' }, from, seq);
});
iosched.forever();
- Client
var Rpc = require('rpc');
var iosched = require('iosched');
var client = new Rpc.Client('RemoteProxy');
var state = 0;
setInterval(function() {
if (state) {
state = 0;
client.call('dev_off', { dev: 0 }, (reply) => {
console.log('dev_off:', reply);
});
} else {
state = 1;
client.call('dev_on', { dev: 0 }, (reply) => {
console.log('dev_on:', reply);
});
}
}, 1000);
iosched.forever();