Trying to cluster Socket.io using net.createServer. All examples are using IP to split what connection goes to witch node. However I'm using 4 servers with a load balancer that points ip;s to the different servers.
So in node cluster I would like to use an unique id to point the connection to a specific cluster.
Figure that each user that wants to connect can add a parameter to the connection url ws://localhost/socket.io?id=xxyyzz
How can I get the connection url in net.createServer
todays code for ip:
var server = net.createServer({ pauseOnConnect: true }, function(connection) {
// We received a connection and need to pass it to the appropriate
// worker. Get the worker for this connection's source IP and pass
// it the connection.
var remote = connection.remoteAddress;
var local = connection.localAddress;
var ip = (remote+local).match( /[0-9]+/g )[0].replace(/,/g, '');
var wIndex = ip % num_processes;
var worker = workers[wIndex];
worker.send('sticky-session:connection', connection);
});
Related
I'm using https://github.com/farhadi/node-smpp in order to create a smpp server.
I'm going to forbid connection if the client's IP address is not in the allowed ips list. For that when a new connection is open I have to check if the credentials are ok and if the IP address is a good one.
The question is how and where can I get the client (ESME's) IP address?
session.on('bind_transceiver', function(pdu) {
session.pause();
const username = pdu.system_id;
const password = pdu.password;
const ipAddress = ''; // WHERE TO GET IT??
if (credentialsAreOk(username, password, ipAddress)) {
session.send(pdu.response());
session.resume();
} else {
session.close();
}
});
When an ESME is connecting to your server, a session is created.
The network socket used by this TCP connection, which is a net.Socket class (https://nodejs.org/api/net.html#net_class_net_socket), is stored inside this session in the socket property.
const socket = session.socket;
So you can easily access this socket property of the session and get the remoteAddress (the clients IP) from there (https://nodejs.org/api/net.html#net_socket_remoteaddress).
const ipAddress = session.socket.remoteAddress;
I have an azure Queue trigger function that has this code:
using (var client = new TcpClient(AddressFamily.InterNetworkV6))
{
client.Client.DualMode = true;
client.Connect(endpoint);
var data = Encoding.ASCII.GetBytes("test");
using (var outStream = client.GetStream())
{
outStream.Write(data, 0, data.Length);
}
}
The error I am getting back:
A connection attempt failed because the connected party did not
properly respond after a period of time, or established connection
failed because connected host has failed to respond
The endpoint address looks correct and this code works when I debug locally, so I suspect that the azure server might not be allowing the outbound connection.
Any ideas why this connection is not working?
Update: This is still not working and I have tried generating the client in the following ways:
// DualMode IPV6
var client = new TcpClient(AddressFamily.InterNetworkV6);
client.Client.DualMode = true;
client.Connect(endpoint);
// SingleMode Internetwork
var client = new TcpClient(AddressFamily.InterNetwork);
client.Connect(endpoint);
// Just Endpoint
var client = new TcpClient(endpoint);
client.Connect(endpoint);
// Normal
var client = new TcpClient(hostAddress, port);
// Forced IPV6
var client = new TcpClient("::ffff:" + hostAddress, port);
Debugging locally, all of these methods except for "forced IPV6" work just fine. On the server, I get these errors:
== DualMode IPV6
Failed PingBack: A connection attempt failed because the connected party did not properly
respond after a period of time, or established connection failed because connected host
has failed to respond [::ffff:204.16.184.62]:3164
== SingleMode Internetwork
Failed PingBack: A connection attempt failed because the connected party did not properly
respond after a period of time, or established connection failed because connected host
has failed to respond 204.16.184.62:3164
== Just Endpoint
Failed PingBack: The requested address is not valid in its context
== Normal
Failed PingBack: A connection attempt failed because the connected party did not properly
respond after a period of time, or established connection failed because connected host
has failed to respond 204.16.184.62:3164
== Forced IPV6
Failed PingBack: The requested address is not valid in its context [::ffff:204.16.184.62]:3164
Looking at your TcpClient instance,
var client = new TcpClient(AddressFamily.InterNetworkV6)
there's no IPv6 in Azure Functions yet. Switch your AddressFamily to v4:
var client = new TcpClient(AddressFamily.InterNetwork)
There are no restrictions on outbound desinations in App Service/Functions.
How to implement client side multiplexing using thrift in nodejs?
I tried the below code, but in vain.
var transport = thrift.TBufferedTransport;
var protocol = thrift.TBinaryProtocol;
var multiplexer = thrift.Multiplexer;
var ip = 'localhost';
var port = 9090;
var connection = thrift.createConnection(ip, port, {
transport : transport,
protocol : protocol
});
multiplexer();
var client = multiplexer.prototype.createClient(
"myServiceName", myServiceClient, connection
);
When I use the above client and call a method/function that is defined in my service,
connection is being made smoothly (no connection error) and
service method/function runs smoothly and returns the output.
But upon receiving the data (buffered) connection.js in thrift npm module throws "Cannot set property '0' of undefined" error.
On further investigation I found that seqid which is set on each client creation, is not being set.
Can someone please help me on this?
I found this to be the solution for the client:
var transport = thrift.TBufferedTransport;
var protocol = thrift.TBinaryProtocol;
var multiplexer = thrift.Multiplexer;
var ip = 'localhost';
var port = 9090;
var connection = thrift.createConnection(ip, port, {
transport : transport,
protocol : protocol
});
var multiplexer = new thrift.Multiplexer();
var client = multiplexer.createClient(
"myServiceName", myServiceClient, connection
);
I have setup Redis cluster in Google compute Engine by click to deploy option. Now i want to connect to this redis server from my node js code using 'ioredis' here is my code to connect to single instance of redis
var Redis = require("ioredis");
var store = new Redis(6379, 'redis-ob0g');//to store the keys
var pub = new Redis(6379, 'redis-ob0g');//to publish a message to all workers
var sub = new Redis(6379, 'redis-ob0g');//to subscribe a message
var onError = function (err) {
console.log('fail to connect to redis ',err);
};
store.on('error',onError);
pub.on('error',onError);
sub.on('error',onError);
And it worked. Now i want to connect to redis as cluster, so i change the code as
/**
* list of server in replica set
* #type {{port: number, host: string}[]}
*/
var nodes =[
{ port: port, host: hostMaster},
{ port: port, host: hostSlab1},
{ port: port, host: hostSlab2}
];
var store = new Redis.Cluster(nodes);//to store the keys
var pub = new Redis.Cluster(nodes);//to publish a message to all workers
var sub = new Redis.Cluster(nodes);//to subscribe a message channel
Now it throw this error:
Here is my Redis cluster in my google compute console:
Ok, I think there is a confusion here.
A Redis Cluster deployment is not the same than a number of standard Redis instances protected by Sentinel. Two very different things.
The click-to-deploy option of GCE deploys a number of standard Redis instances protected by Sentinel, not Redis Cluster.
ioredis can handle both kind of deployments, but you have to use the corresponding API. Here, you were trying to use the Redis Cluster API, resulting in this error (cluster related commands are not activated for standard Redis instances).
According to ioredis documentation, you are supposed to connect with:
var redis = new Redis({
sentinels: [{ host: hostMaster, port: 26379 },
{ host: hostSlab1, port: 26379 },
{ host: hostSlab2, port: 26379 } ],
name: 'mymaster'
});
Of course, check the sentinel ports and name of the master. ioredis will manage automatically the switch to a slave instance when the master fails, and sentinel will ensure the slave is promoted as master just before.
Note that since you use pub/sub, you will need several redis connections.
hello all
I looked at the at the redis-node-client source (relevant part is shown bellow) and I see that it connects to redis via the 'net' package, which is TCP based.
line 370
exports.createClient = function (port, host, options) {
var port = port || exports.DEFAULT_PORT;
var host = host || exports.DEFAULT_HOST;
var client = new Client(net.createConnection(port, host), options);
client.port = port;
client.host = host;
return client;
};
I was wondering if there's a more direct client for redis, preferably via domain-sockets or something of that sort. Im using redis localy, as cache, without going over the wire so its unnecessary to encode/decode messages with TCP headers...
thank you
Unix Domain Socket support appears to have landed in Redis as of Nov 4th.
http://code.google.com/p/redis/issues/detail?id=231
To connect to a Unix Domain Socket, you need to supply the pathname to net.createConnection. Maybe something like this in redis-node-client:
exports.createSocketClient = function (path, options) {
var client = new Client(net.createConnection(path), options);
client.path = path;
return client;
};