3

For testing purposes, I've set up this little script:

Client = require('mysql').Client, client = new Client(); 
client.user = 'root'; client.password = 'root'; client.port = 8889;

counter = 0; data = '';
setInterval(update, 10);

function update(){
    counter++; request();
}
var sys = require('sys'), fs = require('fs'), http = require('http'),
    url = require('url'),port = 8001;

http.createServer(function(request, response) {
    response.writeHead(200, {
        'Content-Type': 'text/html'
    }); response.end('Hello world');
}).listen(port);

function request(){
    client.connect();
    client.query('USE db');
    client.query(
    'SELECT * FROM table', function selectCb(err, results, fields) {
        if (err) { throw err; }
        if(results.length > 0)
        {
            var firstResult = results[0];
            data = firstResult['data'];
        }
        client.end();
    }
    );
}

It works fine, but, after an hour or so, the server crashes and outputs the following error:

node.js:180
        throw e; // process.nextTick error, or 'error' event on first tick
        ^
Error: EADDRINUSE, Address already in use

UPDATE

I updated the code. It now includes some mysql. This definitely is causing the problem, although I don't know exactly why. Leaving this part out stabilizes the loop. Also, I updated the time interval to every 10 ms. (The server crashes after a few minutes with the mysql part in it, but keeps on running without)

16
  • What about listening on another port? Commented Jul 20, 2011 at 8:52
  • @pimvdb - Would that make a difference? Commented Jul 20, 2011 at 8:53
  • Personally, I've used random ports like 15382 without that error so far, so it might be worth a try. Commented Jul 20, 2011 at 8:54
  • I'm trying it as we speak, but out of curiosity, how would that make a difference? Commented Jul 20, 2011 at 9:09
  • 2
    Perhaps you'd want to try connecting once and execute a query each 10ms without disconnecting. Connecting 100 times a second doesn't sound like a good idea. Commented Jul 20, 2011 at 12:18

2 Answers 2

3

You really should honor pimvb's comment about not connecting 100 times a second to the database. If node-mysql doesn't clean up the connections correctly or immediately this will most likely have you run out of available ports for connections within about an hour (actually more like 10 minutes or so, use netstat | grep WAIT | wc -l to see how many closed connections you have pending).

Also, you should be aware of the asynchronous nature of JavaScript/node.js. You might not want to run new queries in such a tight loop while other queries are still pending. This will only pile up and the SQL server will choke.

UPDATE

Something like the following should prevent you from choking your server. It will issue as many request as possible but no more than 1 every 10 ms. Disclaimer: hacked in so textbox, not tested!

Client = require('mysql').Client, client = new Client(); 
client.user = 'root'; client.password = 'root'; client.port = 8889;

counter = 0; data = '';

client.connect(function {
    setInterval(update, 10);

    var queryPending = false, queryReIssue = false;

    function update(){
        if (queryPending) {
            queryReIssue = true;
        } else {
            request();
        }
        counter++;
    }
    var sys = require('sys'), fs = require('fs'), http = require('http'),
        url = require('url'),port = 8001;

    http.createServer(function(request, response) {
        response.writeHead(200, {
            'Content-Type': 'text/html'
        }); response.end('Hello world');
    }).listen(port);

    function request(){
        requestPending = true;
        client.query('USE db');
        client.query('SELECT * FROM table', function selectCb(err, results, fields) {
            requestPending = false;
            if (err) { console.log('ERROR: ' + err.message) }
            if(results.length > 0) {
                var firstResult = results[0];
                data = firstResult['data'];
            }
            if (queryReIssue) {
                queryReIssue = false;
                request();
            }
        });
    }
});
Sign up to request clarification or add additional context in comments.

5 Comments

You are right about the pile of queries. I'm trying out some node stuff and this was just an experiment.
It's not just because they are alot, but due to the nature of node.js and asynchronous IO it is possible (and actually very likely if there's a large dataset in your table), that you will issue the next query before the previous query finished. That is propably the case here, this would also explain, why you run out of available ports: after an hour ~65000 queries (and with them 65000 open connections) piled up, because you query and connect more often than the SQL server can handle.
TL;DR: do not query your sql server again before the previous query's callback was called and do not connect back to the sql server before the end()'s callback (wich you don't even use) was fired.
How would I prevent this from happening?
Looks good. Thanks for the insights! This will definitely help with understanding Node. Powerful stuff.
2

You are connecting every 10ms, which puts a heavy load on your MySQL server. I do not know how it's possible that you get a 'address in use' error, but you might want to try connecting once and use the connection to execute queries.

Just like you don't log out and log back in again and again at a messenger application for each message you want to send to someone :)

1 Comment

I actually believe this alone might not fix the problem. Watch your node process and your sql server process closely. I predict either of them or both will keep growing in memory usage until either of them crashes.

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.