Nginx and Node.js - Utilizing server to fullest - node.js

For experimental/learning purposes (lets assume my application has lot of persistent/concurrent traffic), I have a VM running docker. For docker, I have following setup:
Everything has its own container and communicates with ports. I am trying to simulate two different servers (Nginx), load-balanced by HAProxy.
Now it works all fine and well, but as far as I think, Node is still running in just single thread.
The only configuration Nginx contains is for being reverse proxy to Node (everything else is default). Each Nginx server handles only one domain per server (Node).
Should I use Node Cluster for multi-threaded approach?
Or (assuming each server has 2 cores) should I create two node instances for each Nginx server and have it load balance? In this approach, I am unsure about how load-balancing would work. If there are two Node instances, load balanced by Nginx (or HAProxy), then it would look something like:
Now the reason I want Nginx is for static caching and stuff like DDOS protection. Does that really make sense? Or should I just have one Nginx load-balance between all four Node servers without HAProxy (the reason I am bringing in HAProxy is because some research showed it to be faster/more-reliable than Nginx (unconfirmed)).
Still new to this. Basically, I want to simulate two servers with two cores each running Node.js, reverse proxied by Nginx for static caching etc., and load-balanced by HAProxy.

Found the answer (a while ago, but just updating this post in case it helps someone).
Nginx can run multiple worker processes. So we can just use multiple virtual server blocks to implement this. The current approach I followed with Docker/Nginx/Node is:
Nginx server block 1: This listens to all requests on port 81. And this forwards all those requests to a node instance (lets call it node1).
Nginx server block 2: This listens to all requests on port 82. And forwards all of them to another node instance (lets call it node2).
In simple words, one server block communicates with node1 and another with node2, where node1 and node2 are two node instances (separate docker containers).
These are then load balanced by HAProxy. Where the server configuration is (in accordance with docker) as follows:
server n1 nginx:81
server n2 nginx:82
nginx is the container name. Nginx currently runs 2 worker processes.
(Add whatever http/tcp checks required, this is just minimal configuration).
Open to suggestions for a better approach.

Related

Node.js multiple domain web hosting

I have a VPS server (ubuntu)
wanted multiple node.js sites to be running on it, thus multiple domains
Was trying out
kubernetes with ha and docker images(containers) per website /But memory consumption would increase and the deployment is complex.
What i Need
I don't care if the database instance is shared
each website can have a own database in the database instance.
Node.js must run in the background, has got some env variables.
Simplest routing based on domain names to node.js port like 3000, 4000, 5000 and so on ..
I would advise using NGINX as described here, Setting up an Nginx Reverse Proxy

Do I need a different server to run node.js

sorry if this is a wrong question on this forum but I am simply just stuck and need some advice. I have a shared hosting service and a cloud based hosting server with node.js installed. I want to host my website as normal but I also want to add real time chat and location tracking using node.js I am confused with what I am reading in several places because node.js is itself a server but not designed to host websites? So I have to run 2 different servers? One for the website and one to run node.js? When I setup the cloud one with a node.js script running I can no longer access the webpages.
Whats the best way for me achieve this as I am just going round in circles. Also is there a way I can set up a server on my PC and run and test both of these together before hand so I see what is needed and get it working as it will stop me ordering servers I dont need.
Many thanks for any help or advice.
Node can serve webpages using a framework like Express, but can cause conflicts if run on the same port as another webserver program (Apache, etc). One solution could be to serve your webpages through your webserver on port 80 (or 443 for HTTPS) and run your node server on a different port in order to send information back and forth.
There are a number of ways you can achieve this but here is one popular approach.
You can use NGINX as your front facing web server and proxy the requests to your backend Node service.
In NGINX, for example, you will configure your upstream service as follows:
upstream lucyservice {
server 127.0.0.1:8000;
keepalive 64;
}
The 8000 you see above is just an example, you may be running your Node service on a different port.
Further in your config (in the server config section) you will proxy the requests to your service as follows:
location / {
proxy_pass http://lucyservice;
}
You're Node service can be running in a process manager like forever / pm2 etc. You can have multiple Node services running in a cluster depending on how many processors your machine has etc.
So to recap - your front facing web server will be handling all traffic on port 80 (HTTP) and or 443 (HTTPS) and this will proxy the requests to your Node service running on whatever port(s) you define. All of this can happen on one single server or multiple if you need / desire.

NodeJs instead of Apache

I have a website under domain (say example.com) which is hosted on Amazon Web Services EC 2 instance which has Apache already installed and ready to run on port 80.Now I wish to transfer from Apache to node JS (where Node JS runs on another port, say 8001).How to change the HTTP port address of EC 2 say that when i go to that URL (example.com) it should run on node JS instead of Apache (While for temporary,node JS runs on example.com:8001).
How is it possible and Kindly help?
So you cannot direct a standard web address (e.g. www.example.com) to anything other than port 80. By default http is on port 80 and https is on port 443. You can override that default by explicitly giving the port but you cannot change that default.
So your options are:
Replace Apache with Node on port 80. This will involve shutting down Apache (and making sure it doesn't auto restart on reboot), and changing your node port to port 80. This also will probably require running your node service as root (as port 80 is usually protected) and this is not recommended (Apache starts as root to get the port but then usually immediately switches to non-root user).
Have Apache proxy forward requests to Node. This means Apache is still your main webserver and listens on port 80 but certain requests are sent on to Node.
This second option could be done using mod_proxy with config like this:
ProxyPass "/foo" "http://localhost:8001/"
ProxyPassReverse "/foo" "http://localhost:8001/"
It all depends on what you want to use your set up for and making best use of the software available to you.
Typical set up is a multi-layered approach involving one or more of these:
LoadBalancer (optional for high load sites or where resiliency is key)
Webserver
Appserver
Database
Yes you could use just Node for all of these layers. However, to me, it is more an application server than a webserver.
A webserver like Apache or Nginx is specifically designed to act like a web server, and by that I mean serving static pages and doing other top layer stuff. They have several features built up over their years to provide speed and security. Now nearly everything they can do, can be done in Node but not quite as easily and not by standard and often requires pulling in 3rd party modules.
A webserver then typically offloads dynamic work to other programs. This could be scripts (PHP or Perl), or separate app servers like Tomcat, Jboss or Node. These are typically very good at specific tasks (e.g. talking to database and generating dynamic pages) but less good at severing static pages quickly.
The beauty of node to me is for micro- services, where you can have lots of independent, but potentially interlinked, node services which are all lightweight and good at one task and the web server is still needed in front of them. This compares to a bulky multi-tasking J2EE server like Tomcat or Jboss that you would use in the past which tried to do every dynamic app under one process (though admittedly often under separate WAR files).
So, without knowing your full use case, I would suggest Apache and Node instead of Node replacing Apache.

Node socket.io on load balanced Amazon EC2

I have a standard LAMP EC2 instance set-up running on Amazon's AWS. Having also installed Node.js, socket.io and Express to meet the demands of live updating, I am now at the stage of load balancing the application. That's all working, but my sockets aren't. This is how my set-up looks:-
--- EC2 >> Node.js + socket.io
/
Client >> ELB --
\
--- EC2 >> Node.js + socket.io
[RDS MySQL - EC2 instances communicate to this]
As you can see, each instance has an installation of Node and socket.io. However, occasionally Chrome debug will 400 the socket request returning the reason {"code":1,"message":"Session ID unknown"}, and I guess this is because it's communicating to the other instance.
Additionally, let's say I am on page A and the socket needs to emit to page B - because of the load balancer these two pages might well be on a different instance (they will both be open at the same time). Using something like Sticky Sessions, to my knowledge, wouldn't work in that scenario because both pages would be restricted to their respective instances.
How can I get around this issue? Will I need a whole dedicated instance just for Node? That seems somewhat overkill...
The issues come up when you consider both websocket traffic (layer 4 -ish) and HTTP traffic (layer 7) moving across a load balancer that can only inspect one layer at a time. For example, if you set the ELB to load balance on layer 7 (HTTP/HTTPS) then websockets will not work at all across the ELB. However, if you set the ELB to load balance on layer 4 (TCP) then any fallback HTTP polling requests could end up at any of the upstream servers.
You have two options here. You can figure out a way to effectively load balance both HTTP and websocket requests or find a way to deterministically map requests to upstream servers regardless of the protocol.
The first one is pretty involved and requires another load balancer. A good walkthrough can be found here. It's worth noting that when that post was written HAProxy didn't have native SSL support. Now that this is the case it might be possible to just remove the ELB entirely, if that's the route you want to go. If that's the case the second option might be better.
Otherwise you can use HAProxy on its own (or a paid version of Nginx) to implement a deterministic load balancing mechanism. In this case you would use IP hashing since socket.io does not provide a route-based mechanism to identify a particular server like sockjs. This would use the first 3 octets of the IP address to determine which upstream server gets each request so unless the user changes IP addresses between HTTP polls then this should work.
The solution would be for the two(or more) node.js installs to use a common session source.
Here is a previous question on using REDIS as a common session store for node.js How to share session between NodeJs and PHP using Redis?
and another
Node.js Express sessions using connect-redis with Unix Domain Sockets

How to serve different node.js applications using the same port?

I have a site for hosting my dev projects. Each project is a node.js file. The problem is I can only have 1 project online at the same time - except if I host them in a different ports. But suppose I want to publish 2 projects like that: my_site.com/foo, my_site.com/bar, where the first is managed by "foo.js" and the second by "bar.js". How can I do that?
You need a proxy in front. You assign each separate node process a different port. The proxy forwards traffic on port 80 to the appropriate backend node process.
This can be accomplished with node-http-proxy (https://github.com/nodejitsu/node-http-proxy), or any web server. Nginx and lighttpd make it ridiculously easy, Apache less so but still completely doable.
Setup a Nginx process to reverse proxy to your Node processes. The Nginx process will hold onto the port and send requests for my_site.com/foo to the node foo.js backend process and send requests for my_site.com/bar to the node bar.js backend process.
This way your Node processes stay completely independent and can easily be separated out to different servers later if one of them becomes popular.
If you are using express/connect, you can use something along the lines of
var bar = require("./bar"),
foo = require("./foo");
app.use(express.vhost("my_site.com/bar", bar));
app.use(express.vhost("my_site.com/foo", foo));
Is A Separate File.
NOTE: Not Tested

Resources