📜 ⬆️ ⬇️

Nginx + server Javascript

... or how to switch from PHP + JavaScript to JavaScript + JavaScript


The idea to implement a project on server side JavaScript has been around for a long time. The problem was the lack of suitable server software. Existing open projects did not suit for various reasons. Installing an additional module for Apache was not a good idea, because the performance and optimization of memory usage would not be at its best. Using jslibs, you can configure FastCGI, but I really didn’t want to leave even the slightest chance of “502 Bad Gateway”, the ngx_http_js_module project remained in the embryonic stage, and ngxv8 is not developed enough to implement real applications. So I decided to make my own implementation of server javascript. And try to immediately program all the basic functionality so that you can test it in conditions close to reality.

As the main web server, it was decided to use nginx , as a “javascript engine” - TraceMonkey (a javascript engine from Mozilla Firefox , formerly SpiderMonkey), and write a module for nginx that would “stick together” them. Nothing complicated at first glance, but I really wanted to have a certain functionality (and it worked out!) So that you could work normally further. Most of the ideas are borrowed, by the way, from PHP .Plus some other features (tools for templating, for creating configuration files, etc.), but I did not include them in the main list - they can be made possible by the language features of TraceMonkey.

From words - to business! How to compile and configure how to test and compare ...
')
I do not go deep into the parts of the assembly, otherwise the text will turn out to be incredible sizes. Users who have experience of “building” programs under Linux will feel quite comfortable, and for everyone else I can offer a binary build and the opportunity to skip the self-compilation process.

You will need:The assembly procedure is as follows.

First NSPR latest version (at the time of writing - 4.8.2):

wget ftp://ftp.mozilla.org/pub/mozilla.org/nspr/releases/v4.8.2/src/nspr-4.8.2.tar.gz<br/>tar -xzf nspr-4.8.2.tar.gz<br/>cd nspr-4.8.2/mozilla/nsprpub<br/>./configure --prefix=/usr/local --with-pthreads<br/>make<br/>sudo make install<br/>
Then TraceMonkey from the repository (at the time of writing, version 1.8.5 in the repository, and you can download the source file only for 1.7.0):

hg clone http://hg.mozilla.org/tracemonkey/<br/>cd tracemonkey/js/src<br/>autoconf2.13<br/>./configure --prefix=/usr/local --with-nspr-prefix=/usr/local --with-system-nspr --with-pthreads --enable-threadsafe<br/>make<br/>sudo make install<br/>
This step can be problematic for several reasons. First, not everyone has the hg command. And secondly, all Mozilla Firefox sources are downloaded from the repository. Therefore, the first line of code can be replaced and download the source code only TraceMonkey:

# hg clone http://hg.mozilla.org/tracemonkey/<br/>wget http://js.nnov.ru/files/tracemonkey-20100119.tar.gz<br/>tar -xzf tracemonkey-20100119.tar.gz<br/>
And then compile.

Next nginx (0.8.32) and the javascript module:

wget http://sysoev.ru/nginx/nginx-0.8.32.tar.gz<br/>tar -xzf nginx-0.8.32.tar.gz<br/>cd nginx-0.8.32/src/http/modules<br/>svn co http://nginx-javascript.googlecode.com/svn/trunk/ javascript<br/>cd ../../..<br/>./configure --prefix=/usr/local/nginx-javascript --add-module=src/http/modules/javascript<br/>make<br/>sudo make install<br/>
If everything turned out - go to the setting. Happy owners of the binary assembly will find that the configuration has already been completed, but once again it will not hurt to check it. It is enough to perform the following steps:Having achieved that the server with javascript started working, I wondered how much more profitable this solution was than the standard Apache + PHP. Since the issues of internal optimization of TraceMonkey and PHP worried me somewhat less (for example, which interpreter performs the cycle of a million steps faster? I suspect that the difference is small), the “Hello, people!” Script was tested first.

Participated in the comparison:The testing environment is 4-core Xeon with 2GB of RAM and Debian Etch. All traffic is local. I don’t go into the details of the hardware, the configuration details are also more or less standard.

First, the test cycle of 1000 requests one by one:

# Apache 2.2.14 (prefork) + PHP 5.2.12 (module)<br/>ab -n 1000 http://localhost:8085/hello.php<br/>Time per request: 5.278 [ms] (mean, across all concurrent requests)<br/># nginx (1 worker) + javascript<br/>ab -n 1000 http://localhost:8081/hello.jsx<br/>Time per request: 1.298 [ms] (mean, across all concurrent requests)<br/># nginx (8 workers) + javascript<br/>ab -n 1000 http://localhost:8088/hello.jsx<br/>Time per request: 1.322 [ms] (mean, across all concurrent requests)<br/>
Now the test loop of 1000 requests when creating 100 simultaneous connections:

# Apache 2.2 (prefork) + PHP 5.2 (module)<br/>ab -n 1000 -c 100 http://localhost:8085/hello.php<br/>Time per request: 1.648 [ms] (mean, across all concurrent requests)<br/># nginx (1 worker) + javascript<br/>ab -n 1000 -c 100 http://localhost:8081/hello.jsx<br/>Time per request: 1.277 [ms] (mean, across all concurrent requests)<br/># nginx (8 workers) + javascript<br/>ab -n 1000 -c 100 http://localhost:8088/hello.jsx<br/>Time per request: 0.544 [ms] (mean, across all concurrent requests)<br/>
Conclusions from testing:Besides the fact that such an implementation of server-side javascript makes it possible to achieve an increase in performance compared to traditional PHP, javascript allows using rather clever language constructs.

// id GET, POST cookies:<br/>print($request.get['id'], " ", $request.post['id'], " ", $request.cookie['id']);<br/>// Content-Type:<br/>$result.headers.push("Content-Type: text/html; charset=UTF-8");<br/>// , SELECT , GET, :<br/>var row = (new SQLite("database")).query("SELECT * FROM `table` WHERE `id`=?", $request.get['id']).fetch();<br/>// :<br/>print(File.open("index.html").getChars());<br/>// IP- , :<br/>print({$server.remoteAddr});<br/>
In the last example, there is no syntax error; XML documents can actually be used inside scripts. In this case, you can insert references to variables and calls to functions, enclosing them in braces. This technology, E4X , is very convenient for creating templates. Some more examples can be found at http://js.nnov.ru/nginx/examples.html .

Of course, there are a number of problems that need to be gradually solved:But, in general, you can use. By the way, a small site http://js.nnov.ru is made on JavaScript. Please do not conduct hard tests for fault tolerance :-)

ZY> Special thanks to FTM for an invite, thanks to which the topic is no longer in the sandbox
UPD> At once would publish in thematic, but there were problems with karma. Thanks to all involved!

Source: https://habr.com/ru/post/82511/


All Articles