0

I have a server-client based NODE.JS application.

server.js

...
socket.on('message', function(message) {
    if(message.code == 103)
    {
        process_some_data()
    }
    else
    {
        console.log("UNKNOWN MESSAGE");
    }
});
...

client.js

.. sending responses back to server.js

the process_some_data() function takes about 4 seconds to complete, and when i have just one client it is not a problem, but if i have 10, they all choke and wait till the the last finishes.

I found out that the entire socket event waits till he finishes the current job, for example if i comment process_some_data(), it will not be frozen

I have tried 2 tweaks but the didn't worked :

...
socket.on('message', function(message) {
    if(message.code == 103)
    {
        setTimeout(function() {
            process_some_data();

            console.log("FINISH");
        }, 1)
    }
    else
    {
        console.log("UNKNOWN MESSAGE");
    }
});
...

And even used http://caolan.github.io/async/ ,but no use :

...
socket.on('message', function(message) {
    if(message.code == 103)
    {
        // Array to hold async tasks
        var asyncTasks = [];

        async.series([
            setTimeout(function() {

                process_some_data();

                console.log("FINISH");
            }, 1)
        ], function (err, results) {
            console.log(results);
        });
    }
    else
    {
        console.log("UNKNOWN MESSAGE");
    }
});
...

How to make this ASYNC? Really need this.

Thank you.

5
  • 1
    node run on single thread. so all your solutions will not work. Commented Jan 6, 2017 at 19:31
  • 1
    you can try run the function in another process, it will not block... send a message when it finish and thus it will be async. Commented Jan 6, 2017 at 19:32
  • 1
    It looks like you are doing some blocking IO ops synchronously in process_some_data function. So why does process_some_data function takes so long and why does it block everything?? Commented Jan 6, 2017 at 19:45
  • @Alon how to make that?? Molda -> it is running some linux commands, takes time, i cannot change that Commented Jan 6, 2017 at 20:10
  • 1
    @DancoD We'd need to see process_some_data to tell you how to make it asynchronous (it shouldn't block while the linux commands run, it should move on and resolve a Promise or call a callback once the commands have finished). Commented Jan 6, 2017 at 20:15

1 Answer 1

1

You need multiple processes to solve this with Javascript, because Javascript engines are single-threaded.

What?

When it comes to handling I/O events, such as reading a socket, writing to a file or waiting for a signal, Javascript engines give the appearance of doing multiple things at the same time.

They are actually not: it's just that, under most conditions, processing these events takes so little computation, and the events themselves occur with so much time in between (a microsecond is an eternity for a CPU), that the engine can just process them one after another with plenty of time to spare.

In human time-scale, it looks like the engine is doing a lot of stuff in parallel, but it's just working serially at great speed.

No matter how you schedule your code to run, using setTimeout or Promise, it will still block other events from being processed during the time it's actively computing. Long-running computations (in the scale of seconds, instead of milliseconds) expose the single-threaded nature of the engine: it cannot actually do multiple things at the same time.

Multiple processes

Your computer, however, probably has multiple CPU cores. Unlike the Javascript engine, your hardware is capable of tackling multiple tasks at the same time, at least 1 per core. Even with a single core, your operating system can solve the problem if you run multiple processes.

Since a single Javascript process is single-threaded, you need multiple Javascript processes for this. An easy and time-proven architecture to solve your problem is this:

  • One Javascript program, running in one process, reads from the socket. Instead of calling process_some_data(), however, it puts all incoming messages in a queue.

  • This program then sends items from the queue to another Javascript program, running in a different process, that performs the computation using another CPU core. There may be multiple copies of this second process. In a modern computer, it makes sense to have twice as many active processes as you have CPU cores.

A simple approach for Node is to write an HTTP server, using express, that runs the computationally-intensive task. The main program can then use HTTP to delegate tasks to the workers, while still being able to read from the socket.

This is a good article on the topic of multi-processing with Node, using the cluster API.

Sign up to request clarification or add additional context in comments.

14 Comments

Based on the question's comments it sounds like process_some_data calls some external processes anyway (the 4 seconds isn't due to computation in Javascript), and just needs to be made asynchronous.
Multiple CPU cores also isn't a requirement (however likely). A computer with one core could handle some node.js I/O while the other process is running (albeit paused), because the OS will handle the scheduling and context switching between processes.
Thank you for answering, i get the ideea. What you say with a HTTP server is too complicated (i know how to do it, but it to complicated), but this cluster api might be what i want, i have to understand and test it first. I Have to say, i am disappointed, i mean C# and JAVA catch socket responses in another thread if you feel me ... hoped node did the same ...
@DancoD You don't need a separate thread, you just need to make process_some_data run the other linux commands asynchronously instead of synchronously. Someone will be able to help you with that if you show some of the code for that function.
"i cannot, i need the result of the output and send back to the client" That shouldn't be a problem. You should be able to reply to the client asynchronously.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.