strongloop / strong-cluster-socket.io-store

Implementation of socket.io store using node's native cluster messaging
Other
23 stars 3 forks source link

Usage Howto? #15

Open behrad opened 9 years ago

behrad commented 9 years ago

I have a loopback v2 app using socket.io:

    "loopback": "^2.15.0",
    "loopback-boot": "^2.6.5",
    "loopback-component-push": "^1.4.4",
    "loopback-connector-mongodb": "^1.8.0",
    "loopback-connector-redis": "0.0.3",
    "loopback-datasource-juggler": "^2.26.3",
    "redis": "^0.12.1",
    "socket.io": "^1.3.5",

to fix socket.io when using in clustered mode, I don't know how to setup this store according to docs: http://docs.strongloop.com/display/SOPS/Socket+IO+store+for+clusters I have no access to the master process (no master.js) in loopback app when running by slc run ... my server.js code is put into strongloops cluster workers.

I am attaching socket.io this way in my server.js

var socketIO = require('socket.io');
app.io = socketIO( app.start() );
bajtos commented 9 years ago

to fix socket.io when using in clustered mode, I don't know how to setup this store according to docs: http://docs.strongloop.com/display/SOPS/Socket+IO+store+for+clusters I have no access to the master process (no master.js) in loopback app when running by slc run ... my server.js code is put into strongloops cluster workers.

In your app script, you need to configure socket.io to use a custom session store:

var socketIO = require('socket.io');
var ClusterStore = require('strong-cluster-socket.io-store')(socketIO);
app.io = socketIO( app.start(), { store: new ClusterStore() });

As for configuring the master process, I am not sure if slc run has any support for that. Perhaps @sam-github will know more?

Regardless of the solution, I don't know if this module works with socket.io 1.0. The new version of socket.io uses a new concept of adapters for passing events between nodes, and it relies on sticky sessions to prevent the problem that strong-cluster-socket.io-store was attempting to fix. See http://socket.io/docs/using-multiple-nodes/ for more details.

sam-github commented 9 years ago

Doesn't work with slc run, sorry.

behrad commented 9 years ago

So if it is a strong-cluster-socket.io-store, how couldn't it support strongloop runtime?

With which loopback/strong-pm config we can use this module? Or is this targeting plain node.js cluster module?

sam-github commented 9 years ago

It is targeting plain node cluster module, never saw significant uptake or ue, predates the beginning of work on strong-supervisor by half a year (and of strong-pm by much more), and socket.io 1.x has other mechanisms to deal with this.

I'm sorry you were hoping to use this, perhaps if you decribe the problem you are trying to solve we can provide better suggestions.

behrad commented 9 years ago

I have a loopback 2 app with socket.io with the builtin strongloop cluster support. I was unable to use sticky session (OR socket.io-redis) to fix my websocket issues in clustered mode.

sam-github commented 9 years ago

What version of socket.io, what version of socket.io-redis, and what was the issue?

Using socket.io with external redis is typical use-case, I'm surprised it didn't work.

behrad commented 9 years ago
  "socket.io": "^1.3.5",
  "socket.io-redis": "^0.1.4"

bootstrapped as below:

 app.io = socketIO( app.start() );

  var redis = require('socket.io-redis');
  app.io.adapter(redis({
    host: config.broker.backend.host,
    port: config.broker.backend.port
  }));

but in default non-websocket client connection mode, with polling handshake client complains about the famous websocket error.

jonathan-casarrubias commented 8 years ago

yes because the client is trying to make the handshake with different workers, I was looking if the slc run in production mode was compatible with sticky sessions, so for what Im seeing here is that I need to setup the workers by my own instead of using NODE_ENV="production" slc run, right?

danielfbm commented 8 years ago

any updates on this issue?. I am having the same problem now

masalinas commented 8 years ago

Anybody use socket.io under strong-pm and nginx???. I Have problems to run my socket.io app under strong-pm using the nginx to proxy ...

yagobski commented 8 years ago

Anybody use socket.io under strong-pm?? Please share how to setup socket.io using strong-pm

masalinas commented 8 years ago

Yes I use it What is your problem??

yagobski commented 8 years ago

how can i configure server.js to make socket.io work using strong-pm. When i use slc run it works fine for me but when i deploy in prod using strong-pm it not work. I have this error.

HTTP Response {"code":1,"message":"Session ID unknown"}

I know is the cluster so if you have any example of server.js please share.

masalinas commented 8 years ago

If you use strong-pm, I supouse you are using more than one node, so in this situation you could you the the redis adapter for socket.io.

1) Install redis (sudo apt get install redis-server) in Linux 2) Install redis adapter

npm install socket.io-redis --save

2) In the server.js inject the adapter inside socket.io.

        /* inject socket.io server inside app */
        app.io = require('socket.io')(app.start());

        // configure the socket.io adapter using redis like pubsub messages manager
        // to replicate the events and handshake between all cluster worker process
        var redis = require('socket.io-redis');
        try {
           app.io.adapter(redis({host: 'localhost', port: 6379}));
        }
        catch(err) {
            logger.error('Error connecting to redis' , {fileName: 'server.js', method: 'boot', stack: err.stack});
        }

4) If you are using nginx:

The socket balancesd is made by the master process inside strong-pm so you don't need nginx balancer if you use only one instance, if you use more than one instance you'll need a balancer like nginx capacity.

  ...
   location /socket.io{
        proxy_pass http://app.tachoexplorer.com/socket.io;

        # enables WS support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
...
yagobski commented 8 years ago

This is my server.js and still get the same problem (redis is installed and nothing in logs)

var loopback = require('loopback');
var boot = require('loopback-boot');

var app = module.exports = loopback();

app.start = function() {
  // start the web server
  return app.listen(function() {
    app.emit('started');
    console.log('Web server listening at: %s', app.get('url'));
  });
};

// Bootstrap the application, configure models, datasources and middleware.
// Sub-apps like REST API are mounted via boot scripts.
boot(app, __dirname, function(err) {
  if (err) throw err;

  // start the server if `$ node server.js`
    if (require.main === module) {
        //Comment this app.start line and add following lines
        //app.start();

        app.io = require('socket.io')( app.start() );

        // configure the socket.io adapter using redis like pubsub messages manager
        // to replicate the events and handshake between all cluster worker process
        var redis = require('socket.io-redis');
        try {
            app.io.adapter(redis({host: 'localhost', port: 6379}));
        }
        catch(err) {
            logger.error('Error connecting to redis' , {fileName: 'server.js', method: 'boot', stack: err.stack});
        }

    }
});
masalinas commented 8 years ago

The error that you show is from server side or client side??. When you obtain this error??

The problems that I had was from client-side because I lost some messages, then I used the redis adapter and resolve the problem in the cluster (strong-pm)

yagobski commented 8 years ago

from client side http://xxxx:3000/socket.io/?EIO=3&transport=polling&t=LJY-vzd&sid=MXU5rgpu03dtvJ6LAAAH I get this : {code: 1, message: "Session ID unknown"}

It works the first time but if i refresh the page i get this error

masalinas commented 8 years ago

Ok try this when you create the socket manager in the client side:

var socket = io({transports: ['websocket', 'flashsocket', 'htmlfile', 'xhr-polling', 'jsonp-polling', 'polling']});

With this you force to use websocket.

I use angular.js in the client side so I use angular-socket.io to manage socket like a service. Do you use angular in the client side?

yagobski commented 8 years ago

Yes i use angular in client side

where do you use this var socket = io({transports: ['websocket', 'flashsocket', 'htmlfile', 'xhr-polling', 'jsonp-polling', 'polling']});

masalinas commented 8 years ago

Ok perfect, I use the socket io client side and the angular wrapper over the socket.io client:

"socket.io-client": "~1.4.4",
"angular-socket-io": "~0.7.0"

So in the in the app.js (init file) you define the socket factory like this:

app.config(function ($provide) {
        // inject the Push socket in the app angular module
        $provide.factory('Socket', function (socketFactory, Context) {
            var socket = io({transports: ['websocket', 'flashsocket', 'htmlfile', 'xhr-polling', 'jsonp-polling', 'polling']});

            return socketFactory({ioSocket: socket});
        });

Then you could use this factory like other ...

This is all the configuration in the server side and in the client side than I use under the strong-pm cluster.

danielfbm commented 8 years ago

I had the same issue as you are describing, and for me it was like this: It is hard to control to which node your connection is being redirected by using strong-pm, and mostly the session Id is not shared among all instances, so sending authentication right after connection would always fail for me. I have not trying to control the inbound connections using ngix but I guess that the strong-pm is the one that does the balancing inside the same host. What I did: Created a new project just and I control the connections redirecting to the same worker process, an external load balancer with session control as well to redirect to the same host. In this approach you have to use redis to send messages across nodes. I tried to use socket-io.emitter but it didn't work for me, around 6 months ago. Another approach you can use is to use a MQ and check node by node to find your desired client, etc

yagobski commented 8 years ago

Thanks for your help

talpasco commented 8 years ago

I'm still having trouble implementing socket.io while running "slc run --cluster 4". I'm using the redis adapter, and i tried @masalinas solution with no luck. Any suggestions?

UVk commented 8 years ago

Having the same issue as talpasco. When I tried masalinas suggestion, I was able to get socket connection but no messages where emitted (or received) Any ideas why?