BTC
BTC

Reputation: 4072

NodeJS createServer httpRequest and threads

This is a strange question, but I lack any intuition about how this should work and it is difficult to replicate:

I have a simple web server in NodeJS where I am globally exposing the request that is created:

http.createServer(function(req, res) {
    global.request = req;

    // do something... processRequest();
});

Inside of the "do something," is a function which uses the globalized request:

function processRequest() {
    var request = global.request;
}

Is it possible for a collision to occur between any two instances of global.request?

As I understand it, each connection uses a different thread, pooled in a C worker pool, which would mean the collision was impossible (unless the global context was available across said workers, and such sharing across threads seems difficult if not impossible), but because JavaScript is the vehicle for the connections to be processed, I have a sneaking suspicion that such a collision could be possible.

Any help or pointers on how I can improve this question greatly appreciated.

Upvotes: 0

Views: 1064

Answers (1)

jfriend00
jfriend00

Reputation: 708146

Is it possible for a collision to occur between any two instances of global.request?

Yes, a collision can occur but there are not two instances of global.request. There is only one global state in node.js.

As I understand it, each connection uses a different thread, pooled in a C worker pool

This is not correct. Node.js Javascript is single threaded and all requests run one at a time (or sometimes interleaved), but only on a single thread. node.js does not use individual threads for TCP connections. One thread is used for all networking. There is a C++ thread pool that is used for some disk I/O operations, but the Javascript side of things is still single threaded. The I/O threads are just used to implement an asynchronous behavior which is surfaced through Javascript. Those I/O threads are not related to the networking implementation, but may be part of your confusion in understanding.

In node.js, multiple requests can be "in-flight" at the same time. That means that ANY data which can be accessed by requests needs to be aware of this.

Data can be shared among requests in globally accessible variables, but you cannot store request-specific data in a global because other requests may trounce it.

Node.js Javascript is single threaded which means that a given request will not be pre-emptively interrupted while it is running which simplifies things a lot, but as soon as a request starts an async operation and then finishes it's current thread of execution (waiting for the async callback to be called), then other requests can run. Thus, you can have multiple requests in-flight at the same time.

The usual solution for an issue like your code shows it to NOT store request-specific things in globals at all. Instead, you pass the request/response arguments down to any functions that need to use them. You can store other types of data on the request or response objects themselves too.


So, instead of this:

http.createServer(function(req, res) {
    global.request = req;

    // do something... processRequest();
});

function processRequest() {
    var request = global.request;
}

You must pass the request down to any function that needs it:

http.createServer(function(req, res) {

    // do something... 
    processRequest(req);
});

function processRequest(req) {
    // operate on the request here
}

Upvotes: 2

Related Questions