Blocking instances is implemented in nodejs

  • 2020-05-19 04:11:30
  • OfStack

node.js's native style of single-threaded programming and asynchronous callback functions makes us both happy and sad. Starting with single threads, many people will be puzzled by how the single thread of node.js can achieve high concurrency. This problem is not the focus of this article, point to the end. To clarify 1, the single-threaded node.js only means that the javascript engine is single-threaded. In any case, there is no way to implement multi-threading and blocking in javascript (the method used in this article is also not synchronized through the V8 engine); But other aspects of node.js don't mean you can't multithread, such as IO. If now node js suffered a large number of requests, the requests are IO intensive, so the node every accept a request, to meet a time-consuming longer IO operation, javascript thread will not be one straight in this waiting, but the hand control, add the callback stack IO operation to be performed after the completion of the operation of the (when the callback levels, access number is too large, a large number of callback chain may burst stack). During that time, node.js can process other requests. Therefore, for node.js, although javascript is single-threaded and can only process one request at a time, javascript usually takes a short time to process one request (for IO intensive applications). As long as it can be processed asynchronously, this request will release the control in the process so that node.js can process other requests. While making concurrent requests, IO is actually in a concurrent state, reducing the number of threads processing requests and saving resources to increase the number of threads in IO, which undoubtedly brings performance improvements for IO intensive requests that usually take a long time.

In this way, we emphasize IO intensive rather than node.js's strengths. Accordingly, its weakness is CPU intensive requests. The simple reason is that javascript does not concurrency and can only process other requests after one has been completed. The longer one request takes to process, the longer the other requests wait. Only one request will be processed at the same time, and concurrency performance is low.

Having said that, I want to make a point: node.js should not be blocked; Methods that can be processed asynchronously (e.g., using fs.readFile () instead of fs.syncReadFile () fs.readFileSync ()).

Just because you can't block in node doesn't mean you can't block outside node. We talked about fibers earlier, but now we're going to try to block fibers. Take the example of handling one http request:


var Fiber = require('fibers');
var http = require("http");
Fiber(function () {
    var httpFiber = Fiber.current;
    var html = "";
    http.get("http://www.baidu.com", function (res) {
        var dataFiber = Fiber.current;
        res.on("data", function (data) {
            html += data;
        });
        res.on("end", function (data) {
            httpFiber.run();
        });
    });
    Fiber.yield();
    console.log(html);
}).run();

For those of you who are not familiar with yield() and run(), please refer to fibers in node.


fibers does not run in the node process, so blocking within fibers does not affect the overall performance of node. And it's pretty easy to do, just drop the fiber yield when you want to block. To continue running, perform run() to restore fiber. In the example above, we want to block the current program when the http.get request is initiated, and restore the program when all data reception is completed. So we interrupt this fiber with Fiber.yield () after calling http.get. In listening to response, if the end event is triggered to indicate that the data transfer has been completed, Fiber.current.run () is called in end's callback function to restore fiber, so that the subsequent code gets the requested data in a synchronous manner from http.get.

The example above provides only one idea. If you do some abstract encapsulation of this idea, for example, take an asynchronous method that takes a callback function as a parameter and do a one-step coriolization, interrupt after the call, and hijack the callback function to take the code of the recovery program as the callback function. After obtaining the asynchronous data, the program triggers the scheduled callback function, which can basically realize the asynchronous method synchronization. This paragraph said more confusing, basically is the fibers/future implementation idea, if you are interested, please refer to its source code.


Related articles: