6. Januar 2013

NodeJS MySQL pool

6. Januar 2013 - Geschrieben von Martin - 2 Kommentare

Momentan arbeite ich daran Resigame 2.0 auf NodeJS Basis zu entwickeln. Da abzusehen ist, dass auf Resigame wieder sehr hoher Traffic entstehen wird, wird das ganze Performance optimiert entwickelt. Cluster, SQL Pooling, etc.

Gestern habe ich mir ein Modul für den MySQL Pool geschrieben, denn bei vielen NodeJS Applikationen wird entweder für jeden HTTP Request eine MySQL Verbindung verwendet oder eine für alle.

Das Problem bei einer Verbindung pro HTTP Request ist, dass die Verbindungen bei hohen Nutzerzahlen sehr schnell ausgehen (MySQL max connections) und man ggf. ein paar Sekunden auf die nächste freie Verbindung warten muss.

Bei der Methode mit einer Verbindung, die für alle Nutzer verwendet wird, ist natürlich die Performance sehr bescheiden. Aufwändige Querys können die ganze Applikation stark ausbremsen.

Also habe ich einen MySQL Pool entwickelt, dieser wird beim starten der Anwendung erzeugt. Man übergibt die „poolsize“ – also die Anzahl der Verbindungen die hergestellt werden sollen (diese muss natürlich unter der maximalen Anzahl an Verbindungen, die der MySQL Server zulässt liegen) und die Zugangsdaten zum Datenbankserver. z.B.

var pool = new require('/helpers/pool')({
	poolsize: 50,
	mysql: {
		host: 'localhost',
		user: 'root',
		password: 'root',
		database: 'resigame'
	}
});

Querys können nun direkt an den Pool gesendet werden:

pool.query('SELECT * FROM users WHERE userID = ?', [userID], function(err, results) {
	// whatever
});

Der Aufruf fügt den Query zur Warteschlange hinzu und sieht nach ob gerade eine Verbindung frei ist. Wenn ja wird diese gleich verwendet, ansonsten dauert es bis wieder eine Verbindung frei wird. (Ergo, je mehr Benutzer die gleichzeitig auf die Datenbank zugreifen, desto höher die poolsize –> mehr Performance).

Hier der Quellcode, ich werde ihn die Tage noch ein wenig erweitern und dann auf GitHub stellen.

/** 
 * MySQL pool to hold multiple connections to the database server
 *
 * @author	Martin Lantzsch <martin@linux-doku.de>
 */
 
var mysql = require('mysql');
module.exports = function(config) {
	this.freeConnections = [];
	this.queryQueue = [];
 
	this.createConnection = function(details) {
		var connection = mysql.createConnection(details);
		connection.connect();
		connection.number = this.freeConnections.length;
		this.freeConnections.push(connection);
	};
 
	this.query = function(command, params, callback) {
		if(typeof(params) == 'function') {
			callback = params;
			params = [];
		}
 
		this.queryQueue.push({
			command: command,
			params: params,
			callback: callback
		});
		this.work();
	};
 
	this.work = function() {
		var self = this;
		if(self.queryQueue.length > 0) {
			if(self.freeConnections.length > 0) {
				var query = self.queryQueue.shift();
				var connection = self.freeConnections.shift();
				connection.query(query.command, query.params, function(err, results) {
					if(err) throw err;
					query.callback(err, results);
					self.freeConnections.push(connection);
					if(self.queryQueue.length > 0)
						self.work();
				});
			}
		}
	};
 
	for(i = 0; i < config.poolsize; i++) {
		this.createConnection(config.mysql);
	}
 
	return this;
}

2 Antworten zu “NodeJS MySQL pool”

  1. Amfy sagt:

    Hey!

    Beschäftige mich nun auch seit einigen Monaten mit Node.JS. Und bin i.d.R. recht begeistert gewesen… dein Projekt hört sich tatsächlich sehr interessant an… bin auch schon auf ähnliche Probleme gestoßen.
    Wobei ich das einfach bisher der entsprechenden ORM überlassen habe das zu managen :P

  2. Jörg Schröder sagt:

    Hallo Martin, ich würde gern den Pool verwenden. Komm aber mit der Anwendung nicht klar:
    Ich arbeite mit MS Visual Studio 2015 Community und hab ein node-Projekt erstellt. Es ist noch recht einfach, enthält was den Pool betrifft im Wesentlichen nur die server.js. Darin hab ich nun der README folgend eingetragen:
    pool = new require(‚pool‘)({
    poolsize: 50,
    mysql: {
    host: ‚localhost‘,
    user: ‚root‘,
    password: ‚root‘,
    database: ‚mydb‘
    }
    });
    Im selben Ordner wie server.js liegt der Ordner Pool mit deinen zwei Dateien node-mysql-pool.js und der README. Ich bekomme immer Error: Cannot find module ‚pool‘. Auch führender / oder Angabe des Dateinamens hilft nicht. Ich weiß nicht, wie ich das mit npm installieren könnte, und auch EIntragungen in package.json führen zu keinem Erfolg. Was ist unter „After downloading and placing the module,…“ in der README zu verstehen?
    Was mach ich falsch? Tipp wäre sehr nett, danke :)
    Fröhliche Grüße von Jörg

Schreibe einen Kommentar