Node.js blocking an event loop?

I am writing an API and I am stuck at the point where I mix asynchronous and synchronous code depending on the incoming request, take a look at the examples below.

routes.js

module.exports = [ { method: 'GET', path: '/', controller: 'main', action: 'main', description: 'lists the API functionality', access: 'auth' }, { method: 'POST', path: '/users', controller: 'users', action: 'create', description: 'creates a new user', fields: { fullName: { format: { min: 2, max: 64, minWords: 2, disableDoubleSpaces: true }, description: 'the full name of the new user', examples: 'Thomas Richards, Richard Jones, Michael J. Fox, Mike Vercoelen, John Johnson' }, email: { format: { min: 2, max: 64, maxWords: 1, match: 'email' }, description: 'the email address of the new user', examples: ' mike@grubt.com , lilly@gmail.com , thomas.richards@mail.com , peter@mymail.com ' }, password: { format: { min: 2, max: 64 }, description: 'the password of the new user', examples: '123abcdfg, 7373kEjQjd, #8klKDNfk' } } } ]; 

the routes.js file is basically a very important part of the API, it checks incoming data, routes to the correct controller / action and determines if the method is public or requires authentication (basic auth).

api-server.js

 var http = require('http'); var url = require('url'); var os = require('os'); var dns = require('dns'); var apiServer = module.exports; var routes = require('./routes.js'); // Routes file from above. var req, res, controller, action, serverInfo, httpServer; apiServer.start = function(){ prepare(function(){ httpServer = http.createServer(handleRequest).listen(3000); }); }; // // We need to do this function, we need the local ip address of the // server. We use this local ip address in logs (mongoDb) so we can // refer to the correct server. // function prepare(callback){ var serverName = os.hostname(); dns.lookup(serverName, function(error, address){ if(error){ throw error; } serverInfo = { name: serverName, address: address }; callback(); }); } function getRoute(){ // loops through routes array, and picks the correct one... } function getAuth(callback){ // parses headers, async authentication (mongoDB). } function getRequestData(callback){ // req.on('data') and req.on('end'), getting request data. } function parseRequestData(callback){ // parse request data at this point. } function validateRequestData(callback){ // loop through route fields (see routes.js) and validate this data with the ones // from the request. } function requireControllerAndCallAction(){ // do actual job. } function handleRequest(request, response){ req = request; res = response; req.route = getRoute(); // First step for a request, syncronous. if(req.route === false){ // 404... } // If in the routing schema access was "auth", // this route requires authentication, so do that... if(req.route.access === 'auth'){ getAuth(function(error, user){ if(error){ // 401 } else { req.user = user; } } } if(req.method === 'POST' || req.method === 'PUT'){ // Async functions. getRequestData(function(){ parseRequestData(function(){ validateRequestData(function(){ requireControllerAndCallAction(); }); }); }); } else { requireControllerAndCallAction(); } } 

As you can see, some functions are asynchronous (getAuth, getRequestData), and some are synchronous (parseRequestData, validateRequestData).

Now here is what:

Request 1. comes with the POST method, url '/ users' and data:

  • fullName = 'Rick'
  • email: 'rick @'
  • password: 'a'

So, we iterate over the API workflow:

  • get the current route (controller: users, action: create) see the second element of the array in routes.js

  • Get request data and callback: a. analyze data b. data validation

Now let's IMAGINE, the data check will take 5 seconds (which slows down, but only, for example), and during this check a new request arrives, the new request is not processed until the previous one is completed correctly?

+2
source share
1 answer

If they were synchronous, and if they took 5 seconds, then yes, requests for this server instance will be blocked. Therefore, it is important that call blocking (network, db, file system, etc.) cause an asynchronous call. An event loop must contain a loop or all server blocks.

http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/

The key line from this entry:

... however everything works in parallel except your code

This means that expensive I / O must be asynchronous, but your code may be blocked. but usually this is expensive I / O, which we worry about locking on the server.

Your code, as a rule, simply processes callbacks from long I / O calls, updates your state, and then disconnects another call. But this is its beauty - when you update your state, it is in the main cycle of events, so there is no need for multi-threaded access to "your" state and code. No locks, no deadlocks, etc .... but all the advantages of asynchronous and parallel I / O, which are an expensive part.

Another key point (which may take 5 seconds to work without I / O):

In addition to I / O calls, Node.js expects all requests to return quickly; for example, CPU intensive work needs to be divided into another process that you can interact with as events, or using abstractions like WebWorkers.

Also expect 'auth' and 'POST' | "WAY" ever happens at the same request? If so, you may have a problem. getAuth looks like asynchronous, but then you go straight to the req.method check. At this point, getAuth will still work. If you want POST and PUT to be authenticated, then this block of asynchronous methods can be wrapped with the async getAuth method.

+6
source

All Articles