Im actually desperate now. I need to design and code solution I've never even thought I'd be making, and it seems completely unrealistic to achieve (for me) with clean express. But I might be wrong.
What I need is:
REST API - done
Socket.IO server - done
bunch of Socket.IO-client connections - can be done
But now, what I need is to some efficient way of making it, to communicate with each other. So the app has to be basically a bridge between all of them. I was thinking of using some kind of state managing library, like Redux solution, that way I (at least I think) could achieve it pretty easy. But I also haven't found any of this kind, for the node, or neither found how to achieve it on the backend.
So the question is: what's the best solution, to achieve one-to-many and many-to-one communication between multiple socket.io connections? Again, to make it clear.
socket-client connection = connecting to already existing server, as a node app.
I am not speaking of making simple solution for clients to communicate between each other on 1 server. I want to create 1 server, and to connect to multiple others.
Okay, so, what you probably want to do is to create one "server" application, then connect your Electron app as well as the bots as clients to that server.
For the bots, which would be running as their own node scripts, you would be using the socket.io-client package, and then use that the same way you use the client in the browser. Call io() with your connection settings, get a socket from that, and start binding your events as usual:
let io = require('socket.io-client');
let socket = io('http://YOUR_SERVER_IP/');
socket.on('connect', function(){});
socket.on('event', function(data){});
socket.on('disconnect', function(){});
If you want to tell the difference between the bots and the Electron clients, I would send out some special event on connect, that your server can then handle:
socket.on('connect', function(){
socket.emit('identify_as_bot', {id: IDENTIFIER})
});
I hope that helps.
Related
I am developing a website where I will use microservices.
I will have a couple or more Node.js application that will use Socket.io.
I was trying to figure out how I will architecture this.
Can I use multiple Node.js with Socket.io connecting to a user or will I run into conflicts? I can use NGiNX as a proxy a an UUID to identify which microservice to send the request to. Does that make sens? Is there a better way?
Or I was also thinking of using a Node.js has a proxy that receives all the Socket.io connection and then it creates a connection with the user. But this seems to be adding to the network load because I am adding a another microservice.
Anyways, I would love your views on this.
You can setup multi nodejs services and all of them using socket.io-redis lib connect to a Redis server to share socketID of all nodejs services. That mean you storage all socket info on Redis server. When you emit an event they will automatically emit to all nodejs services.
const server = require('http').createServer();
const io = require('socket.io')(server);
const redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
io.on('connection', socket =>{
// put socket of user to a room name by user_id
socket.join(user_id);
});
// emit an event to a specify user, all nodejs keep that user connection will be emit
io.to(user_id).emit('hello', {key: 'ok'})
Depending of how your project goes, it might or might not be a good idea to build microservices communication over Socket.io
The first thing that comes to mind are the poor guarantees of the socket.io messaging system, especially the fact that your messages are not stored on disk. While this might be convenient, this is also a real problem when it comes to building audit trails, debugging or replayability.
Another issue I see is scalability/cluster-ability: yes you can have multiple services communicating over one nodeJS broker, but what happens when you have to add more? How will you pass the message from one broker to the other? This will lead you to building an entire message system and you will find safer to use already existing solutions (RabbitMQ, Kafka...)
I built an app and i'm planning to make a real time battle with Angular 2 and laravel. For example, you hit the "attack" button, and your opponent see his life going down in real time.
My app built with:
frontend: Angular 2
Backend: PHP Laravel 5.2
Now I'm searching and learning for my real time battle component,
and I saw different guides and tutorials for it:
https://www.codetutorial.io/laravel-5-and-socket-io-tutorial/
http://4dev.tech/2016/02/creating-a-live-auction-app-with-angular-2-node-js-and-socket-io/
The first tutorial is about how to use Laravel 5 and socket io.
The second one is how to use Angular 2 with NODS JS and socket io.
When I say real time, I mean that both users see the same thing that is happening on the screen)
My Backend and Frontend are totally divided and I have no setup with NodeJS anywhere in my app.
Both users need to see actions happening during a battle in my app, and It need to go through my laravel API and shown via my Angular 2 battle component
My question is -
What's the best approach to real time app (seem websockets) using Angular2 and Laravel 5.2 to get the desired result of what I'm trying to achieve?
Laravel in this context is just templating and serving the client files, and acting as an interface inbetween the client and the socket.io server. It doesn't actually act as the socket.io server, and I don't believe it can.
So yes, you would still need something (node) to host the socket.io server to interact with the client, through PHP or otherwise. Personally, I'd skip Laravel/PHP altogether and just use node with koa/express/whatever to template your client (html/js/css/etc) files. Feels like an unnecessary abstraction to me.
The code below from socket.blade.php already has a connection to the actual socket.io server, so I don't see why the additional overhead of an HTTP POST through PHP/Laravel is a good idea. Security, perhaps, but you can handle that with the actual socket.io server as well.
var socket = io.connect('http://localhost:8890');
socket.on('message', function (data) {
$( "#messages" ).append( "<p>"+data+"</p>" );
});
For the real-time character of your use-case, websockets are definitely the way to go. The players that should get the updates should be in the same 'room', so you can broadcast changes more easily. For the other functionality you can either use websockets or regular API calls to your backend directly from your client-side app code with some kind of communication between your api and the socket server, e.g. through Redis.
TLDR:
All data through sockets, node server does api calls and broadcasts changes to active players
Use API from app directly, use pub/sub queue foo for communication between laravel and node to broadcast changes to active players
Option 1:
Angular frontend app
Set up websocket connection
Add triggers for game foo which will send data over the socket connection and is handled by your nodeserver
Only talks to sockets
Node server
Serves frontend app
Handles socket connections, divide players per game
Handles socket calls and calls laravel api to do mutations on your data
Process action and broadcast changes to players in game X
Laravel REST API
Auth x
Default CRUD foo
Option 2:
Angular frontend app
Talks to api directly
Uses sockets to listen for updates
Node server
Serves frontend app
Handle websocket data
Listen on queue for published data from API
Broadcast changes to players in game x over socket
Laravel REST API
Auth
Crud
Mutation x triggers publish in Redis or other queue, which the node server can/should listen on
I'm sure there are more ways you can set this up, you just have to decide where you want what. Maybe introducing Redis is something you do not want, in that case your node app will have more to do. If you do want to use something like Redis, you'll need to do API calls from either your frontend app or choose to do it through the node app anyway, combining the 2 options.
If you are planning to use websockets then there seems to be less use of laravel as only one socket is pretty capable of handling all the data that will be exchanged between the frontend and the backend, so if you don't mind changing your engine you can try Meteor, https://www.meteor.com/
I want to add on an existing project some sockets with nodeJs and Socket.io.
I already have 2 servers :
An API RESTful web service, to storage and manage my datas.
A Public web service to return HTML, assets (js, css, images, ...)
On the first try, I create my socket server on the Public one. But I think it will be better if I create an other one to handle only socket query.
What do you think ? It's a good idea or just an useless who will add more problem than solve (maybe duplicate intern lib, ..)
Also, i'm using token to communicate between Public and API, do I have to create another to communication between socket and API ? Or I can use the same one ?
------[EDIT]------
As nobody didn't understand me well I have create a schema with the infrastructure I was thinking about.
It is a good way to proceed ?
The Public Server and Socket server have to be the same ? Or can be separate ?
Do I must create a socket connection between API and Socket server for each client connected ?
Thank you !
Thanks for explaining better.
First of all, while this seems reasonable, this way of using Socket.io is not the most common one. The biggest advantage of using Socket.io is that it keeps a channel open for 2-way communication. The main advantage of this is that the server itself can send messages to the client without the latter having to poll periodically.
Think, for example, of a mail client. Without sockets, the browser would have to poll periodically to check for new mail. With an open socket connection, instead, as soon as a new mail comes the server notifies the client immediately.
In your case, the benefits could be limited, and I'm not sure the additional complexity of a Socket.io server (and cost!) would really be worth the modest speed improvement on REST requests. However, at the end it's up to you.
In answer to your points
See above
If the "public server" is not written in Node.js they can't be the same application. Wether they reside on the same server, it's up to you and your budget. Ideally they should be separate, for bigger workloads.
If you just want the socket server to act as a real-time proxy, then yes, you'll have to create a socket connection for each request. How that will work is:
The client requests a resource to the Socket.io server.
The Socket.io server does the normal HTTP request to the API server (e.g. using request)
The response is returned to the client over the socket connection
The workflow represented in #3 is the reason why you should expect only moderate performance improvement. Indeed, you'll get some better latency, but most of the overhead for starting a HTTP request is still there!
I'm trying to figure out how a chat app with lots of "rooms" would be implemented with nodejs and socket.io.
I know there are plenty of tutorials around for 1 room chats that run on 1 port, but my question is how would I transform something like that to support multiple chat rooms?
Would it require a different port per room? If so how would I get the server to sniff out open ports for this?.. or is there a better approach?
The target clients are native mobile sdks like iOS and android, so how would I get the server to open a room for a GET request?
Please excuse my noobness, I'm really trying to learn.
I have to point you to ActionHeroJS, namely the built-in chat server. This is accomplished with a single websocket port on the server, where each connection and each room is stored inside Redis. When a message is broadcast to a room, only those connections in that room get the message.
I might encourage you to try out the framework as an alternative to starting from scratch, but definitely look at the concepts as a way to manage a chat system at scale, beyond single-room-tutorials.
I am trying to scale a simple socket.io app across multiple processes and/or servers.
Socket.io supports RedisStore but I'm confused as to how to use it.
I'm looking at this example,
http://www.ranu.com.ar/post/50418940422/redisstore-and-rooms-with-socket-io
but I don't understand how using RedisStore in that code would be any different from using MemoryStore. Can someone explain it to me?
Also what is difference between configuring socket.io to use redisstore vs. creating your own redis client and set/get your own data?
I'm new to node.js, socket.io and redis so please point out if I missed something obvious.
but I don't understand how using RedisStore in that code would be any different from using MemoryStore. Can someone explain it to me?
The difference is that when using the default MemoryStore, any message that you emit in a worker will only be sent to clients connected to the same worker, since there is no IPC between the workers. Using the RedisStore, your message will be published to a redis server, which all your workers are subscribing to. Thus, the message will be picked up and broadcast by all workers, and all connected clients.
Also what is difference between configuring socket.io to use redisstore vs. creating your own redis client and set/get your own data?
I'm not intimately familiar with RedisStore, and so I'm not sure about all differences. But doing it yourself would be a perfectly valid practice. In that case, you could publish all messages to a redis server, and listen to those in your socket handler. It would probably be more work for you, but you would also have more control over how you want to set it up. I've done something similar myself:
// Publishing a message somewhere
var pub = redis.createClient();
pub.publish("messages", JSON.stringify({type: "foo", content: "bar"}));
// Socket handler
io.sockets.on("connection", function(socket) {
var sub = redis.createClient();
sub.subscribe("messages");
sub.on("message", function(channel, message) {
socket.send(message);
});
socket.on("disconnect", function() {
sub.unsubscribe("messages");
sub.quit();
});
});
This also means you have to take care of more advanced message routing yourself, for instance by publishing/subscribing to different channels. With RedisStore, you get that functionality for free by using socket.io channels (io.sockets.of("channel").emit(...)).
A potentially big drawback with this is that socket.io sessions are not shared between workers. This will probably mean problems if you use any of the long-polling transports.
I set up a small github project to use redis as datastore.
Now you can run multiple socket.io server processes.
https://github.com/markap/socket.io-scale
Also what is difference between configuring socket.io to use redisstore vs. creating your own redis client and set/get your own data?
The difference is that, when you use 'RedisStore', the socket.io itself will save the socket heartbeat and session info into the Redis, and if you use cluster with node.js, the user client can work.
Without redis, the client might change the node.js process next time, so the session will be lost.
The difference is, if you have a cluster of node.js instances running, memStore won't work since it's only visible to a single process.