| 
				
					 | 
			2 years ago | |
|---|---|---|
| .. | ||
| lib | 2 years ago | |
| node_modules | 2 years ago | |
| History.md | 2 years ago | |
| LICENSE | 2 years ago | |
| README.md | 2 years ago | |
| index.js | 2 years ago | |
| package.json | 2 years ago | |
Sharing Connection among Multi-Process Nodejs
As we know, each Node.js process runs in a single thread. Usually, we split a single process into multiple processes to take advantage of multi-core systems. On the other hand, it brings more system overhead, sush as maintaining more TCP connections between servers.
This module is designed to share connections among multi-process Nodejs.
normal (without using cluster client)
+--------+   +--------+
| Client |   | Client |   ...
+--------+   +--------+
    |  \     /   |
    |    \ /     |
    |    / \     |
    |  /     \   |
+--------+   +--------+
| Server |   | Server |   ...
+--------+   +--------+
using cluster-client
             +-------+
             | start |
             +---+---+
                 |
        +--------+---------+
      __| port competition |__
win /   +------------------+  \ lose
   /                           \
+--------+     tcp conn     +----------+
| Leader |<---------------->| Follower |
+--------+                  +----------+
    |
+--------+
| Client |
+--------+
    |  \
    |    \
    |      \
    |        \
+--------+   +--------+
| Server |   | Server |   ...
+--------+   +--------+
Packet structure
0       1       2               4                                                              12
+-------+-------+---------------+---------------------------------------------------------------+
|version|req/res|    reserved   |                          request id                           |
+-------------------------------+-------------------------------+-------------------------------+
|           timeout             |   connection object length    |   application object length   |
+-------------------------------+---------------------------------------------------------------+
|         conn object (JSON format)  ...                    |            app object             |
+-----------------------------------------------------------+                                   |
|                                          ...                                                  |
+-----------------------------------------------------------------------------------------------+
+----------+             +---------------+          +---------+
| Follower |             |  local server |          |  Leader |
+----------+             +---------------+          +---------+
  |     register channel     |       assign to        |
  + -----------------------> |  --------------------> |
  |                          |                        |
  |                                subscribe          |
  + ------------------------------------------------> |
  |       subscribe result                            |
  | <------------------------------------------------ +
  |                                                   |
  |                                 invoke            |
  + ------------------------------------------------> |
  |          invoke result                            |
  | <------------------------------------------------ +
  |                                                   |
$ npm install cluster-client --save
Node.js >= 6.0.0 required
'use strict';
const co = require('co');
const Base = require('sdk-base');
const cluster = require('cluster-client');
/**
 * Client Example
 */
class YourClient extends Base {
  constructor(options) {
    super(options);
    this.options = options;
    this.ready(true);
  }
  subscribe(reg, listener) {
    // subscribe logic
  }
  publish(reg) {
    // publish logic
  }
  * getData(id) {
    // invoke api
  }
  getDataCallback(id, cb) {
    // ...
  }
  getDataPromise(id) {
    // ...
  }
}
// create some client instances, but only one instance will connect to server
const client_1 = cluster(YourClient)
  .delegate('getData')
  .delegate('getDataCallback')
  .delegate('getDataPromise')
  .create({ foo: 'bar' });
const client_2 = cluster(YourClient)
  .delegate('getData')
  .delegate('getDataCallback')
  .delegate('getDataPromise')
  .create({ foo: 'bar' });
const client_3 = cluster(YourClient)
  .delegate('getData')
  .delegate('getDataCallback')
  .delegate('getDataPromise')
  .create({ foo: 'bar' });
// subscribe information
client_1.subscribe('some thing', result => console.log(result));
client_2.subscribe('some thing', result => console.log(result));
client_3.subscribe('some thing', result => console.log(result));
// publish data
client_2.publish('some data');
// invoke method
client_3.getDataCallback('some thing', (err, val) => console.log(val));
client_2.getDataPromise('some thing').then(val => console.log(val));
co(function*() {
  const ret = yield client_1.getData('some thing');
  console.log(ret);
}).catch(err => console.error(err));
delegate(from, to):
create delegate method, from is the method name your want to create, and to have 6 possible values: [ subscribe, unSubscribe, publish, invoke, invokeOneway, close ],  and the default value is invokeoverride(name, value):
override one propertycreate(…)
create the client instanceclose(client)
close the clientAPIClientBase  a base class to help you create your api clientcluster issuecluster-client to wrap DataClientDataClient
const Base = require('sdk-base');
class DataClient extends Base {
  constructor(options) {
    super(options);
    this.ready(true);
  }
  subscribe(info, listener) {
    // subscribe data from server
  }
  publish(info) {
    // publish data to server
  }
  * getData(id) {
    // asynchronous API
  }
}
APIClient
const DataClient = require('./your-data-client');
const { APIClientBase } = require('cluster-client');
class APIClient extends APIClientBase {
  constructor(options) {
    super(options);
    this._cache = new Map();
  }
  get DataClient() {
    return DataClient;
  }
  get delegates() {
    return {
      getData: 'invoke',
    };
  }
  get clusterOptions() {
    return {
      name: 'MyClient',
    };
  }
  subscribe(...args) {
    return this._client.subscribe(...args);
  }
  publish(...args) {
    return this._client.publish(...args);
  }
  * getData(id) {
    // write your business logic & use data client API
    if (this._cache.has(id)) {
      return this._cache.get(id);
    }
    const data = yield this._client.getData(id);
    this._cache.set(id, data);
    return datal
  }
}
|------------------------------------------------|
| APIClient                                      |
|       |----------------------------------------|
|       | ClusterClient                          |
|       |      |---------------------------------|
|       |      | DataClient                      |
|-------|------|---------------------------------|
For more information, you can refer to the discussion