{"id":4172,"date":"2013-01-02T17:34:07","date_gmt":"2013-01-02T13:34:07","guid":{"rendered":"http:\/\/blog.denivip.ru\/?p=4172"},"modified":"2013-08-05T14:10:33","modified_gmt":"2013-08-05T10:10:33","slug":"pitfalls-in-large-scale-application-development-on-node-js","status":"publish","type":"post","link":"http:\/\/blog.denivip.ru\/index.php\/2013\/01\/pitfalls-in-large-scale-application-development-on-node-js\/?lang=en","title":{"rendered":"Pitfalls in Large-Scale Application Development on Node.js"},"content":{"rendered":"<p><center><a href=\"http:\/\/blog.denivip.ru\/wp-content\/uploads\/2012\/12\/nodejs-hell.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4122\" title=\"nodejs-hell\" src=\"http:\/\/blog.denivip.ru\/wp-content\/uploads\/2012\/12\/nodejs-hell.jpg\" alt=\"\" width=\"470\" height=\"288\" srcset=\"http:\/\/blog.denivip.ru\/wp-content\/uploads\/2012\/12\/nodejs-hell.jpg 470w, http:\/\/blog.denivip.ru\/wp-content\/uploads\/2012\/12\/nodejs-hell-300x183.jpg 300w\" sizes=\"(max-width: 470px) 100vw, 470px\" \/><\/a><\/center><\/p>\n<p>It has become clear that Node.js has become a striking trend in the community of Web developers. In this post, we are going to discuss, what pitfalls may encroach on the developer in Node.js, and whether it is worth switching to it.<\/p>\n<p>Basically, developers associate Node.js with small services, e.g., chats. (For more details, read <a href=\"http:\/\/blog.denivip.ru\/index.php\/2012\/11\/%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0-%D0%B2%D1%8B%D1%81%D0%BE%D0%BA%D0%BE%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D1%85-%D1%81\/\">&quot;Development of high-performance services for Node.js&quot;).<\/a> Well, they have a good reason for that. Node.js is a perfect fit for services that support a permanent connection to the client or can wait for a response for a long time. Absence of I\/O lock allows you to read large files, keeping your service ready to process new requests. <!--more--><\/p>\n<p>So, that&#8217;s why the community is so fond of Node.js:<\/p>\n<p>\u2022\tThe Node can maintain thousands of open connections with clients, while constantly saving the data to the database.<br \/>\n\u2022\tThe event-based model works great to make cascaded asynchronous requests to other parts of the application.<br \/>\n\u2022\tA large and responsive community combined with a fast speed of the technology development.<br \/>\n\u2022\tDozens of modules supported.<br \/>\n\u2022\tJSON is the native format of object description. Moreover, if you use <a href=\"http:\/\/www.mongodb.org\/\">MongoDB<\/a>, you may virtually forget of the serialization issue.<\/p>\n<p>By the way, Node.js also allows to quickly implement highly loaded REST services. This is greatly simplified by such modules as <a href=\"http:\/\/expressjs.com\/\">express<\/a>.<\/p>\n<p>However, there is a reverse side of the coin.<\/p>\n<h2>Unlockable Flow?<\/h2>\n<p>There is an erroneous opinion that node.js can not be locked. From the architectural viewpoint, Node is built to run everything in a single flow. It means that, heavy math can easily hang the application for a while.<\/p>\n<p>So, how to deal with it?&nbsp; There are several approaches to solving this problem. All of them leverage the idea of taking heavy computations off the control flow. Here they are:<\/p>\n<ol>\n<li>Break the code down into iterations and run them using setTimeout with a delay of 0 ms. Please keep in mind that 0 here in no way means no delay at all. It means that the node will start executing the code as soon as possible. Of course, you will have to store intermediate results somewhere. Also, all this would lead to extended time needed to execute such computations.<\/li>\n<li>Delegate execution to workers. Essentially, this approach will generate additional system processes to run your code.<\/li>\n<\/ol>\n<h2><strong>File read\/write and collisions<\/strong><\/h2>\n<p>If you exchange the contents of large files between workers, you should be aware of specifics of accessing them. When opening a file, the Node will fetch its description from the system. Then, the description will be passed to workers.<\/p>\n<p>Also, often you need to notify workers or other Node&#8217;s instances of making file manipulations. Usually you need to lock a file from other processes to prevent parallel write to it. For such purposes, a separate controller node is written to grant read\/write permissions to other nodes and organize the read\/write waiting queue.<\/p>\n<p>Please note that this approach is applicable not just to file manipulations, but to any task involving collision control.<\/p>\n<h2><strong>Garbage Collector Execution Lock<\/strong><\/h2>\n<p><center><strong><a href=\"http:\/\/blog.denivip.ru\/wp-content\/uploads\/2012\/12\/garbage.jpeg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-4128\" title=\"garbage\" src=\"http:\/\/blog.denivip.ru\/wp-content\/uploads\/2012\/12\/garbage-279x300.jpg\" alt=\"\" width=\"279\" height=\"300\" srcset=\"http:\/\/blog.denivip.ru\/wp-content\/uploads\/2012\/12\/garbage-279x300.jpg 279w, http:\/\/blog.denivip.ru\/wp-content\/uploads\/2012\/12\/garbage.jpeg 465w\" sizes=\"(max-width: 279px) 100vw, 279px\" \/><\/a><\/strong><\/center><\/p>\n<p>As you know, Node.js is built around the V8 engine. Its specifics is that when you start GC, the node stops until GC terminates. The delay time depends on the number of objects in the heap. &quot;Running&quot; applications performance may somewhat degrade due to the garbage collector. To display GC results, run the node as follows:<\/p>\n<p><em>node<\/em> &lt;script&gt; &#8212;trace-gc<\/p>\n<p>In one approach, the application is split into several parts to reduce the number of objects inside a single system module. Then running the garbage collector in each of the modules will take less time. However the idea is good, you should remember that the code of asynchronous modules should be concerted, engendering complex constructions.<\/p>\n<p>So, careful and mindful creation of objects should be your main paradigm in writing services in Node.js. <\/p>\n<h2><strong>Pitfalls in Debugging<\/strong><\/h2>\n<p>Debugging of the node is not an easy task. Of course, you can just run the node in the debug mode. However the debugging experience here is quite poor. It is much easier to use a third-party application, e.g.:<\/p>\n<p>1) <a href=\"https:\/\/github.com\/dannycoates\/node-inspector\">node-inspector<\/a><\/p>\n<p>This product allows you to remotely debug the node in the WebInspector interface, edit the runtime code and even profile your application.<\/p>\n<p>Below is a short video on debugging the node using node-inspector<\/p>\n<p><center><object classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" width=\"500\" height=\"375\" codebase=\"http:\/\/download.macromedia.com\/pub\/shockwave\/cabs\/flash\/swflash.cab#version=6,0,40,0\"><param name=\"allowFullScreen\" value=\"true\" \/><param name=\"allowscriptaccess\" value=\"always\" \/><param name=\"src\" value=\"http:\/\/www.youtube.com\/v\/AOnK3NVnxL8?hl=ru_RUinterface &amp;version=3\" \/><param name=\"allowfullscreen\" value=\"true\" \/><embed type=\"application\/x-shockwave-flash\" width=\"500\" height=\"375\" src=\"http:\/\/www.youtube.com\/v\/AOnK3NVnxL8?hl=ru_RU&amp;version=3\" allowscriptaccess=\"always\" allowfullscreen=\"true\"><\/embed><\/object><\/center><\/p>\n<p>2) PHPStorm\/WebStorm Node.js Debugger<\/p>\n<p>These editors have built-in features for local and remote node debugging in their native environment.<\/p>\n<p>The event model built into Node.js can easily confuse the developer. The output of the stack consisting of a sequence of invocations of callback functions, is usually not informative. However, you can improve readability of the output, if you make it a rule to give names to all your callbacks. For example:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;width:540px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/><\/div><\/td><td><div class=\"text codecolorer\">setTimeout (function do () {\/ * Some code here * \/});<\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<p>Now at stack output, you will not get lots of messages relating to unnamed function calls.<\/p>\n<h2><strong>Callback function cascading<\/strong><\/h2>\n<p> Complex Node.js based applications imply sequential call of many callbacks. Quite often, the following structures can be seen in the code:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;width:540px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/><\/div><\/td><td><div class=\"text codecolorer\">do(function () { ... function() { ... function() { ... } } });<\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<p>It is extremely difficult to read and maintain such code. To structurize your code in such situations, you can use special patterns. For more details about them, read the post <a href=\"http:\/\/book.mixu.net\/ch7.html\">&quot;Node.js Control flow&quot;.<\/a><\/p>\n<h2><strong>API variations<\/strong><\/h2>\n<p>The Node and its modules are rapidly changing. So there are risks that the newer versions of Node.js and its modules could break the whole application. It means that you have to be prepared, while migrating to a newer API, create new implementations of entire service blocks.<\/p>\n<p>For this reason, we recommend to avoid installing any module globally. The situation is quite possible, as two different nodes on the same machine may use two incompatible versions of the same module.<\/p>\n<p><em>npm install &lt;module&gt;<\/em><\/p>\n<h2><strong>Examples of successful use of Node.js<\/strong><\/h2>\n<p>On GitHub, there is a list of companies that use Node.js in their services. You can access it by clicking <a href=\"https:\/\/github.com\/joyent\/node\/wiki\/Projects,-Applications,-and-Companies-Using-Node\">here.<\/a><\/p>\n<p>Let&#8217;s take a look at some of them:<\/p>\n<ul>\n<li>Based on Node.js, <a href=\"http:\/\/yahoo.com\/\">Yahoo<\/a> has implemented the <a href=\"https:\/\/github.com\/yahoo\/mojito\">Mojito<\/a> framework; it allows you to write both client-side and server-side applications, depending on which device they run.<\/li>\n<li><a href=\"https:\/\/www.yammer.com\/\">Yammer<\/a> uses a Node.js based service functioning as a cross-domain proxy for  requests sent to the API. The main benefit outlined by Yammer&#8217;s developers is the node&#8217;s capability to serve many simultaneous requests.<\/li>\n<li><a href=\"http:\/\/bocoup.com\/\">Bocoup<\/a> has been written on the IRC_bot&#8217;s node. They have chosen this technology based on the server-side JavaScript paradigm (Bocoup has lots of JS developers)<\/li>\n<\/ul>\n<h2><strong>Summary<\/strong><\/h2>\n<p>It is only for you to decide whether to use Node.js or not, based on the nature of your particular task. However, you should understand that Node.js has its specific strengths and weaknesses.<\/p>\n<h2>Helpful links<\/h2>\n<ul>\n<li><a href=\"http:\/\/thomashunter.name\/blog\/php-vs-nodejs\/\">PHP + Apache Stack vs Node.js<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dannycoates\/node-inspector\">Node inspector<\/a> &#8212; debugging and profiling tool<\/li>\n<li><a href=\"http:\/\/www.jetbrains.com\/webstorm\/webhelp\/running-and-debugging-node-js.html\">Running and Debugging Node.Js in WebStorm<\/a><\/li>\n<li><a href=\"http:\/\/book.mixu.net\/ch7.html\">Node.js Control flow<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>It has become clear that Node.js has become a striking trend in the community of Web developers. In this post, we are going to discuss, what pitfalls may encroach on the developer in Node.js, and whether it is worth switching to it. Basically, developers associate Node.js with small services, e.g., chats. (For more details, read [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[489,23,277,460,102],"_links":{"self":[{"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/posts\/4172"}],"collection":[{"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/comments?post=4172"}],"version-history":[{"count":2,"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/posts\/4172\/revisions"}],"predecessor-version":[{"id":4174,"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/posts\/4172\/revisions\/4174"}],"wp:attachment":[{"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/media?parent=4172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/categories?post=4172"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/tags?post=4172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}