Comparing "hello world" on EC2 Micro between node and nginx, why node so slow? - node.js

I've hit the need to put a load balancer in front of some Node.js servers and I decided to compare Nginx and Node.js
To do this test I simply spun up an Ec2 Micro (running Ubuntu 14.04) and installed Nginx and Node.js
My nginx.conf file is:
user www-data;
worker_processes 1;
pid /run/nginx.pid;
http {
server {
listen 443 ssl;
return 200 "hello world!";
ssl_certificate /home/bitnami/server.crt;
ssl_certificate_key /home/bitnami/server.key;
}
}
events {
worker_connections 768;
}
And my Node.js code is:
var http = require('https');
var fs = require('fs');
var serverOptions = {
key: fs.readFileSync("/home/bitnami/server.key"),
cert: fs.readFileSync("/home/bitnami/server.crt")
};
http.createServer(serverOptions,function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(443);
console.log('Server running');
I then used another EC2 server (m3.medium due to memory needs) to run wrk with the command
./wrk -t12 -c400 -d30s https://ec2-54-190-184-119.us-west-2.compute.amazonaws.com
The end result was that Nginx could consistently pump through 5x more reqs/second than Node.js (12,748 vs 2,458), while using less memory (both were CPU limited).
My question is, since I'm not exactly great/experienced/knowledgeable in server admin or setup, am I doing something to severely mess up Node.js? And can I confidently draw the conclusion that in this situation, Nginx is absolutely the better choice?

Related

Run node.js server file using apache default port

I have this node.js server file:
var app = require('http').createServer(handler),
io = require('socket.io').listen(app),
fs = require('fs'),
app.listen(80);
function handler (req,res){
fs.readFile("/client.html"), function(err, data) {
if (err) {
console.log(err);
res.writeHead(500);
return res.end('Error loading client');
}
res.writeHead(200);
res.end(data);
});
}
is there a way to make this node.js file run automatically through the apache default port number when a client tries to connect without having to run it through the cmd ?
without having to run it through the cmd
Short answer: not quite. Think of this node.js file as creating a server on a par with Apache.
The script creates a server .createServer() and then tells it to listen to port 80 .listen(80).
Since socket.io is bound to this node server (and can't just be plugged in to Apache) you will have to execute the script (run it through the cmd) to be able to utilize it.
That being said:
I'm sure one could make a daemon (a background program) out of the node server; thus firing it up automatically on system start. If you then specify to run it on port xxxx you could tell Apache to map this port into its own local space (its folders). On a local machine this instruction would look like this: ProxyPass /app http://127.0.0.1:xxxx/
There would be two servers running on one machine; and Apache's http://127.0.0.1/app would redirect to the node server (listening to xxxx).
I would not advise to go down that rabbit hole just yet. To start having fun with socket.io on windows just create a batch file with the command to run your server: node [path/to/your/server_file.js] for ease of use. Expand your node script. And stop using Apache. (Express is a nice module to use node for web content...)

Node.js web server

I would like to access http://mypublicIP:2888 with Node.js running on mypublicIP and port. The server times out! Does anyone know why this is happening? What can I try to do to identify the underlying problem?
EDIT
I believe if you don't specify the IP address, Node should be reachable from all network interfaces. Node code:
// Load the http module to create an http server.
var http = require('http');
// Configure our HTTP server to respond with Hello World to all requests.
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("Hello World\n");
});
server.listen(2888);
// Put a friendly message on the terminal
console.log("Server running somewhere....");
on the apache machine:
check that node is actually listening on port 8000
check that it's reachable from localhost
check that the request appears in apache's access_log
check if anything relevant appears in apache's error_log
these translate to (on Linux):
netstat -tnlpe | grep -w 8000
telnet localhost 8000
tail /var/log/apache/access_log
tail /var/log/apache/error_log

Load balance request traffic with muiltiple Node servers using NGINX

According to this answer:
You should run multiple Node servers on one box, 1 per core and split request traffic between them. This provides excellent CPU-affinity and will scale throughput nearly linearly with core count.
Got it, so let's say our box has 2 cores for simplicity.
I need a complete example a Hello World app being load balanced between two Node servers using NGINX.
This should include any NGINX configuration as well.
app.js
var http = require('http');
var port = parseInt(process.argv[2]);
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(port);
console.log('Server running at http://localhost:' + port + '/');
nginx configuration
upstream app {
server localhost:8001;
server localhost:8002;
}
server {
location / {
proxy_pass http://app;
}
}
Launch your app
node app.js 8001
node app.js 8002
HttpUpstreamModule documentation
Additional reading material
cluster module - still experimental, but you don't need nginx
forever module - in case your app crashes
nginx and websockets - how to proxy websockets in the new nginx version

Muitliple Node.js servers using NGINX proxys

The Goal:
Use muitiple live node.js servers independent of each other under different doc roots.
Using NGINX
server {
server_name .lolwut1.com;
root /var/www/html/lolwut1;
# proxy pass to nodejs
location / {
proxy_pass http://127.0.0.1:5001/;
}
}
server {
server_name .lolwut2.com;
root /var/www/html/lolwut2;
# proxy pass to nodejs
location / {
proxy_pass http://127.0.0.1:5002/;
}
}
/var/www/html/lolwut1/app.js
var http = require('http');
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("lolwut1\n");
});
server.listen(5001);
/var/www/html/lolwut2/app.js
var http = require('http');
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("lolwut2\n");
});
server.listen(5002);
So when I...
node app.js in /var/www/html/lolwut1/app.js and hit lolwut1.com I'm all good.
Questions:
But now what If I want to start the second node server?
Is this a bad approach?... Am I thinking about this the wrong way?
What are the advantages/disadvantages of using node.js with a connect.vhost directive as a router rather than NGINX?
Use forever to start and stop your node apps.
You're doing it right! This approach has worked well for me for quite a while.
Connect vhost Advantage: You don't have to install and configure nginx. The whole stack is node.js.
Nginx Advantage: Nginx is a mature and stable web server. It's very unlikely to crash or exhibit strange behavior. It can also host your static site, PHP site, etc.
If it were me, unless I needed some particular feature of Nginx, I'd pick Connect vhost or node-http-proxy for the sake of having an all-node.js stack.
But now what If I want to start the second node server? Is this a bad approach?...
when you cd to /var/www/html/lolwut2/ and run node app.js, this should start the second server on port 5002 and lolwut2.com should work.
Am I thinking about this the wrong way?
That's a valid way to run multiple node apps on the same server if you have enough memory, and plenty of cpu power. This is also a good way to scale a single node app on the same machine to take advantage of multiple cores by running multiple nodes and using the upstream directive (like here https://serverfault.com/questions/179247/can-nginx-round-robin-to-a-server-list-on-different-ports)

node.js server not responding

i am trying this simple demo off of the node.js home page:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
i have opened the port on amazon ec2 (1337) in its security group.
[root#domU-12-31-38-01-8A-8D servers]# /usr/local/bin/node nodeexample.js
Server running at http://127.0.0.1:1337/
i get nothing back but the typical server is not responding. please help this noob out
danke
You're listening to 127.0.0.1 which makes node listen only to the loopback interface and only lets it be be reached from localhost itself.
If you listen to 0.0.0.0 instead, you will listen to all the machine's network interfaces and lets you be reachable over the Internet on any public IP the machine is using. This is probably what you want.

Resources