Nginx for authentication and authorization in Node JS app - node.js

I am developing app in nodejs with expressJS and for performance optimization, I have decided to use Nginx with NodeJS (Based on my conclusion, after reading lots of articles on Nginx + NodeJS).
I have divided tasks for Nginx and NodeJS as follow :
Nginx
Serve static files
Authentication
Authorization
NodeJS
Dynamic API Handling with DB Interaction
Is it good idea to design app in above way?
If yes then how to handle authentication and authorization in Node JS app using Nginx?
If no then what is better way to handle load in NodeJS app?

Your concept is fundamentally flawed. Nginx is fast at what its meant to do, serving content over http. Putting nginx infront of node.js doesn't provide any performance improvements. Nginx can be used as a load balancer to split traffic evenly among several hosts, but in itself doesn't provide any performance benefits except for the fact that its very efficient. That said Nginx is not meant to handle authorizaton/authentication except for maybe http basic auth.
You should be writing your own logic to handle authentication and authorization. To scale you should write your code statelessly, so that you can run across multiple servers. So you should either store session data in a place such as memcache or create a stateless system using something like JWT.
Additionally, you shouldn't be serving content with node.js. Nginx is faster at this. So only serve templates with Node.js, allow Nginx to cache and serve static content. This paradigm also allows you to leverage a content distribution network. This is the only real way to leverage what nginx is good at, serving content.
Optimization isn't about making things go super fast. Optimization is something that occurs when you run into a performance barrier or need to make a system more efficient to prevent premature scaling.

Related

Is it better to serve media(images/video) by creating separate http server listening to it in nodejs?

I am serving media/videos from nodejs application apart from normal REST API calls. I have read somewhere that it is not ideal to serve this, since it may consume CPU in main thread. If we consider this, is it better to create separate http server in same code to serve request to media, so that it does not affect normal REST API calls. Or we can create node cluster to achieve the same ?

Building scalable SPAs using websockets, how complex is it?

I am beginner in web technologies. While studying about frontend frameworks, I came to know that we run separate application servers for frontend and backend server(API).
e.g. If I am using vue.js, I'll be running a vue server for frontend and I'll be running another MEAN stack API server separately. Now my application will need to show real-time updates, I'll have to use websocket connection between my browser and frontend server which further will need websocket/webhook connection with my backend server(API). Now I am already aware of the scalability and session management issues with websocket connection. In this scenario, how should I build my application for better scalability and with less complexity? Is it possible to create a monolithic application server for frontend and backend? Will that be a good choice?
Is it possible to create a monolithic application server for frontend and backend? Will that be a good choice?
That choice is fine; start simple and you can break into microservices in the future. Unless this is for a large production system!
If you use something like express you can serve the Vue.js files using express.static, API endpoints using express.Router() instances, and the ws or socket.io module attached to express instance for websockets.
Now my application will need to show real-time updates, I'll have to
use websocket connection between my browser and frontend server which
further will need websocket/webhook connection with my backend server
This isn't the case. You can have your frontend (the app running in a browser) connect directly to the backend via websocket if you wish, no need to proxy via a frontend server. For session management look into JWT tokens.
You can go for socket.io library in Nodejs. It's simple and easy to use, The scalability and session can be handled by introducing Redis,
check https://socket.io/docs/using-multiple-nodes/

does node.js/ngnix using a intern cache for often used files?

i'm wondering if node.js is using cache for the follow scenario or if a module for that is existing:
When you have for example a web-portal which shows you at the startpage 20 products with images, every time the server has to fetch the images from the hdd or in best case from a ssd.
for every single image just to find it the server need about 5-7 ms.when you have 50 user are visiting the startpage at the same time it would take 20img * 5ms * 50 usr = 5000ms just to find the images on the hdd.
So it would be nice if is there was a way to keep all often used files like images, css, html and so on in the memory.so you just define the cache size. For example 50MB and the module/node.js keep the often used files in the cache.
Node.js itself (by default) doesn't do any caching, although OS and other lower layer elements (e.g., HDD) may do it, speeding up consecutive reads significantly.
If you want to enable cache'ing http responses in nodejs there is a http-cache library - https://www.npmjs.com/package/http-cache and request-caching library - https://www.npmjs.com/package/node-request-caching. For caching files you can use filecache https://www.npmjs.com/package/filecache and for serving static files - serve-static (https://www.npmjs.com/package/serve-static).
If you're using a framework such as Express it's not that simple anymore - for example, running Express in production mode causes it to cache some stuff (like templates or CSS). Also note that res.sendFile streams the file directly to the customer (possibly proxy server, such as nginx)
However, even Express' webpage (http://expressjs.com/en/advanced/best-practice-performance.html) advises to use a separate proxy:
Cache request results
Another strategy to improve the performance in
production is to cache the result of requests, so that your app does
not repeat the operation to serve the same request repeatedly.
Use a caching server like Varnish or Nginx (see also Nginx Caching) to
greatly improve the speed and performance of your app.
For other recommendations about speeding up nodejs you can take a look at https://engineering.gosquared.com/making-dashboard-faster or http://www.sitepoint.com/10-tips-make-node-js-web-app-faster/
The builtin Web server on Nodejs doesn't implement any content cache. Like #prc322 says the specific answer depend on your technology stack on top of Nodejs (framework, middleware, etc.). On the other hand Nginx is more widely used as Web server for static assets. Normally they are combined in some way that the static assets are server from Nginx and the application logic (rest services, etc.) are handled by the Nodejs application. Content caching is part of the HTTP protocol standard and you can benefit of it by setting a HTTP cache like varninsh in front of your Web application.

Nginx - Routing, Capabililties of with Node.js

I am running a Node.js server which is now getting more load and I need to start getting this running on multiple cores, as Node.js is single threaded and can only run on one.
This is a simple solution given the Node.js Cluster module and tons of NPM packages for this very thing.
I have a problem in that I need browser sessions to retain the same Node.js worker after the first request. This is because I store authentication data, etc. in a single node worker process and do not want to open the can of worms of messaging between worker processes, etc. etc.
My browsers store a session id cookie once authenticated, and I want a system to re-route requests to their correct worker based on their session cookie.
Nginx looks promising, but I know nothing about it, and while I will put the work into it, I would like to know before I spend hours diving into it, if it is capable of routing to Node.js worker processes based on arbitrary data from the request header, such as a session cookie.
Is this doable? If I know it is, I'll get down and dirty figuring out Nginx, ground up.
I assume you are storing your sessions in nodejs memory. You might want to store your sessions in redis instead. This way it is persisted outside of a single server, and can be accessed from multiple processes.
In addition to redis, you might also want to look into Amazon Elastic Beanstalk for managing your load-balancing. You can setup an nginx proxy to route your requests to multiple servers based on their load.
This link might be able to get you started http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_nodejs_express_elasticache.html

Running multiple Node apps on Node cluster

We need to deploy multiple Node/Express apps on a set of servers (behind load balancer). These apps are fully independent of each other in terms of functionality. I'll first explain how I am thinking of doing this and then I am looking for input in terms of best practices, if there are any red flags in my design etc.
Here is the setup I am thinking about:
Frontend server behind load balancer will have node-http-proxy running and it'll accept incoming requests on port 80. This reverse proxy will route the requests to appropriate node apps that are running on different ports on this server. for ex:
var http = require('http'),
httpProxy = require('http-proxy');
var options = {
router: {
'myapphost.com/MyFirstApp': 'myapphost.com:3000',
'myapphost.com/MySecondApp': 'myapphost.com:3001'
}
}
// ...and then pass them in when you create your proxy.
var proxyServer = httpProxy.createServer(options).listen(80);
Each of the node app will be running on node cluster using something like Cluster2 to take advantage of multi-core systems.
My questions:
Is this right design and strategy?
Some of our applications need to be stateful. What is the best way to do the state management in this kind of a setup? Using external session storage such as Redis is the right approach? Or pinning a session to a given frontend machine and using in-memory session storage?
UPDATE:
Since I posted this question, after talking to couple of people, there is one more approach that has come up--
I can use Nginx as a reverse proxy and load balancer in front of my frontend machines. Each frontend machine will serve only one app. There can be one more back up machine for that app. (depending upon requirement). So if I have three apps, I'll have three separate machines each one serving different app. All the requests will be received by Nginx on port 80, Nginx reverse proxy will route the request to the right frontend machine. Each machine will have Node cluster to take advantage of multi-core system. Advantage of this approach is-- deployment becomes lot easier for each app. Also, we can scale each app separately.
Please share your thoughts on this approach as well.
This is a right approach, as well you mentioned redis, or you could use any other session storages like connect-mongo or any other session storage.
If you are using Load Balancer, I guess you have multiple instances of same servers? If this is the case, then you need to analyze session performance and how much it will be used, and then decide if you need to shard session storage/database, or one single machine that every balanced instance will be talking to.
You already think the right way, why wont you try and hack some of it, and see if it fits your needs?
As well you need to think about static media, possibly to store it separately (S3 + CloudFront?).
As well as how you are going to deliver updates to instances and restart them while still keeping application logic consistency.
This structure as well enables possibilities for AB testing (you can load balance to specific instances with "testing version" of application. While majority will be balanced across main instances.
It all depends on your scale as well, and sometimes you really don't need that much initially, just be ready to improve and scale in the future.

Resources