4. September 2014

node.js und die Oracle-Datenbank: Erste Versuche ...

node.js and the Oracle database: First experiments
In diesem Blog-Posting möchte ich ein wenig von meinen ersten Gehversuchen mit der Oracle-Datenbank und node.js berichten. node.js selbst möchte ich jedoch nicht im Detail vorstellen, dazu gibt es ausreichend Information im Internet. Auch zum Thema Installation und Setup einer node.js-Umgebung sowie zur Installation zusätzlicher Pakete mit "npm" sind zahlreiche Tutorials verfügbar. Hier geht es vor allem um node.js und die Oracle-Datenbank.
Bekanntlich kann man node.js recht gut mit "JavaScript auf dem Server" bezeichnen. Basis ist die JavaScript-Engine des Chrome-Browsers, die dann JavaScript-Programme per Kommandozeile startet und ausführt. Wie andere Programmiersprachen bietet auch node.js mittlerweile eine recht umfangreiche und erweiterbare Funktionsbibliothek mit, die von der sehr aktiven Community ständig weiterentwickelt wird. Einige Wichtige Eigenschaften von node.js seien aber vorab genannt: Node.js ist Asynchron, event-getrieben und nicht-blockierend. Was das genau bedeutet, sehen wir noch.
Möchte man mit node.js auf eine Oracle-Datenbank zugreifen, stellt sich (wie immer) die Frage nach einem Treiber. Von Oracle gibt es derzeit (noch) keinen node.js Treiber, so dass wir auf das Angebot der Community zurückgreifen müssen - und siehe da: Es existiert ein Oracle-Treiber namens node-oracle von Joe Ferner, den man von GitHub herunterladen kann.
Dem Download liegt ein README bei, welches die Installation in eine bestehende node.js Umgebung beschreibt. Auf Unix/Linux-Systemen gelang mir das auf Anhieb und ohne weitere Probleme. Danach kann man sein erstes node.js-Programm schreiben. Ich greife natürlich auf die Oracle-Datenbank zu, selektiere erst mal etwas und gebe es aus. Das sieht dann so aus.
var oracle = require('oracle');

var connectData = {
  hostname: "sccloud034.de.oracle.com",
  port:     1521,
  database: "pdb01.de.oracle.com", 
  user:     "scott",
  password: "tiger"
}

oracle.connect(connectData, function(err, connection) {
  if (err) {
   console.log("Error connecting to db:", err); return;
  }

  connection.execute("select ename, job from emp ", [],  function(err, results) {
    connection.close();
    console.log(results);
  });
});

console.log("done");
Der Code sieht etwas anders aus, als man es von prozeduralen Programmiersprachen gewohnt ist: node.js arbeitet bei Funktionen, die "I/O bound" sind (Netzwerk, Dateisystem) asynchron. Die Funktion oracle.connect ist I/O bound und bekommt neben den Verbindungsdaten zur Oracle-Datenbank auch eine Callback-Funktion übergeben - diese wird aufgerufen, wenn die Verbindung hergestellt wurde. node.js ist nicht-blockierend: oracle.connect wird asynchron ausgeführt, das Skript arbeitet währenddessen weiter. Demnach muss der Code, der von oracle.connect abhängt, in eine Callback-Funktion gepackt werden.
Startet man das Programm, so bekommt man folgendes Ergebnis.
$ node ora.js
done
[ { ENAME: 'SMITH', JOB: 'CLERK' },
  { ENAME: 'ALLEN', JOB: 'SALESMAN' },
  { ENAME: 'WARD', JOB: 'SALESMAN' },
  { ENAME: 'JONES', JOB: 'MANAGER' },
  { ENAME: 'MARTIN', JOB: 'SALESMAN' },
  { ENAME: 'BLAKE', JOB: 'MANAGER' },
  { ENAME: 'CLARK', JOB: 'MANAGER' },
  { ENAME: 'SCOTT', JOB: 'ANALYST' },
  { ENAME: 'KING', JOB: 'PRESIDENT' },
  { ENAME: 'TURNER', JOB: 'SALESMAN' },
  { ENAME: 'ADAMS', JOB: 'CLERK' },
  { ENAME: 'JAMES', JOB: 'CLERK' },
  { ENAME: 'FORD', JOB: 'ANALYST' },
  { ENAME: 'MILLER', JOB: 'CLERK' } ]
$
Interessant ist, dass das "done", welches im Skript ja erst am Ende ausgegeben wird, dennoch zuerst ausgegeben wurde. Das hängt eben mit der bereits erwähnten asynchronen Natur eines node.js-Programms zusammen. Wenn man sich den Code genau ansieht, so sieht man, dass auf der obersten Ebene nur 2 Statements vorhanden sind: oracle.connect und console.log. Während oracle.connect asynchron abgearbeitet wird, arbeitet node.js mit dem zweiten Statement weiter. Als erstes wird demnach "done" ausgegeben. Erst danach ist der Verbindungsaufbau zu Oracle fertig, node.js ruft die Callback-Funktion auf und führt das eigentliche SELECT durch.
Als nächstes soll ein node.js Skript verwendet werden, um Dateien in die Datenbank hochzuladen. Mit dem Aufruf soll ein Parameter übergeben werden, der auf ein Verzeichnis zeigt - das node.js Skript soll dann alle Textdateien in die Tabelle DOCUMENT_TABLE in der Datenbank speichern. Zuerst also die Tabelle anlegen ...
create table document_table (filename varchar2(200), document clob);
Dann kommt das node.js Skript - es arbeitet eigentlich wie vorhin. Allerdings wird nun, sobald die Verbindung zur Datenbank hergestellt wurde, das angegebene Directory durchgearbeitet und alle gefundenen Dateien werden mit oracle.execute in die Datenbank geladen. Die Arbeit mit den Callback-Funktionen kann, wie man sehen kann, zu stark geschachteltem Code führen. Node.js bietet hier durchaus Ansätze, das soll aber nicht Thema dieses Postings sein.
var fs = require("fs");
var ora = require("oracle");

var oradb = {
  hostname: "sccloud034.de.oracle.com",
  port:     1521,
  database: "orcl",
  user:     "scott",
  password: "tiger"
}

var dirname = process.argv[2];

ora.connect(oradb, function(err, connection) {
  if (err) {throw err;}
  connection.setAutoCommit(false);
  var fileCount = 0;
  fs.readdir(dirname, function (err, files) {
    if (err) {throw err;}
    files.forEach(function (file) {
      fileCount ++;
      fs.readFile(dirname+"/"+file, 'utf-8', function (err, data) {
        connection.execute(
          "insert into document_table values (:1, :2)",
          [file, data],
          function (err, results) {
            if (err) {throw err;} else {
              console.log('"'+file+'" saved.');
              fileCount--;
              if (fileCount == 0) {
                connection.close();
                console.log("done");
              }
            }
        });
      });
    });
  });
});
Nun wurden alle Dateien über genau eine einzige Verbindung an die Oracle-Datenbank gespeichert. Die Dateien werden also sequenziell verarbeitet. Wenn nun auf Datenbankseite mehr Ressourcen bereitstehen, dann würde man auch gerne mehr Datenbankverbindungen nutzen - schreiben wir das Skript also ein wenig um - so dass für jede Datei nun eine neue Verbindung geöffnet wird. Der folgende Code arbeitet sich also zuerst durch die Dateien des angegebenen Verzeichnisses und versucht dann, für jede Datei eine Datenbankverbindung zu öffnen und die Datei an die Datenbank zu senden.
var fs = require("fs");
var ora = require("oracle");

var oradb = {
  hostname: "sccloud034.de.oracle.com",
  port:     1521,
  database: "pdb01.de.oracle.com",
  user:     "scott",
  password: "tiger"
}

var dirname = process.argv[2];

fs.readdir(dirname, function (err, files) {
  if (err) {throw err;}
  files.forEach(function (file) {
    fs.readFile(dirname+"/"+file, 'utf-8', function (err, data) {
      ora.connect(oradb, function(err, connection) {
        if (err) {throw err;}
        connection.execute(
          "insert into document_table values (:1, :2)",
          [file, data],
          function (err, results) {
            if (err) {throw err;}
            console.log('"'+file+'" saved.');
            connection.close();
        });
      });
    });
  });
});
Wenn man dieses Skript startet, passiert erstmal gar nichts ... und nach einer Weile bricht es typischerweise mit einem Fehler ab. Wird mit einer Datenbank gearbeitet, die große Ressourcen bereitstellt, so kann das Skript tatsächlich auch erfolgreich laufen - effizient arbeitet es aber in keinem Fall.
[oracle@sccloud033 node]$ node loadFiles.js po

/home/oracle/node/loadFiles.js:19
          if (err) {throw err;}
                          ^
Error: ORA-12516: TNS:listener could not find available handler with matching protocol stack
Noch klarer wird das ganze, wenn man (während das Skript läuft), die Oracle Data Dictionary View V$SESSION beobachtet.
SQL> select username, count(*) from v$session group by username

USERNAME                         COUNT(*)
------------------------------ ----------
                                       28
SCOTT                                 154
SYS                                     1

-- nach einer Weile ...

SQL> select username, count(*) from v$session group by username

USERNAME                         COUNT(*)
------------------------------ ----------
                                       26
SCOTT                                 366
SYS                                     1

Um dieses Verhalten zu verstehen, muss man wieder an die Tatsache denken, dass node.js asynchron arbeitet. Wenn im Verzeichnis 500 Dateien liegen, sind arbeitet sich das Skript schnell durch diese 500 Dateien durch und versucht, für jede Datei asynchron eine Datenbankverbindung zu öffnen (wie gelernt: Während das läuft arbeitet das Skript weiter). Das aber dauert (im Vergleich zum Lesen des Verzeichnisses) recht lange, so das das Verzeichnis durchgearbeitet ist, noch bevor die erste Datenbankverbindung steht - als Folge entsteht der Bedarf nach 500 Datenbankverbindungen - Oracle kommt gar nicht mehr hinterher.
Es braucht einen Connection-Pool, der die verwendeten Datenbankverbindungen reguliert. Node.js bietet keine Connection-Pools für Datenbankverbindungen an, aber zum Glück hat die Oracle-Datenbank die Lösung. Denn seit der Oracle-Version 11.1 gibt es den Database Resident Connection Pool, der für solche Umgebungen, die keine eigenen Connection-Pools bereitstellen können, geschaffen wurde. Man dachte damals vor allem an PHP - für node.js eignet sich der Pool genauso gut. Aber erst muss der Pool auf Datenbankseite gestartet werden. Das geschieht mit dem PL/SQL-Paket DBMS_CONNECTION_POOL, mit dem auch Einstellungen am Pool vorgenommen werden können. Hier muss allerdings mit DBA-Privilegien gearbeitet werden. Verwendet man Oracle12c, so muss der Connection-Pool in der Container-Datenbank, nicht in der Pluggable Database gestartet und eingerichtet werden.
SQL> exec dbms_connection_pool.start_pool;

PL/SQL-Prozedur erfolgreich abgeschlossen.
Dieser Connection Pool ist nicht mit der Shared Server Architektur vergleichbar. Die Datenbank verwaltet nun selbstständig einen Pool von Dedicated Server-Verbindungen. Wie bei jedem Connection Pool kann man die minimale und maximale Anzahl der gehaltenen Verbindungen einstellen. Wenn ein Client eine Verbindung braucht, wird der Dedicated Server Prozess nicht neu erzeugt, er wird aus dem Pool genommen - und beim Schließen der Verbindung wird er an den Pool zurückgegeben. Wenn gerade keine Verbindung frei ist, wartet der Client solange bis eine frei ist. Das ist genau das, was wir für node.js brauchen. Zuerst stellen wir noch die minimale und maximale Anzahl Verbindungen ein.
begin
  DBMS_CONNECTION_POOL.ALTER_PARAM ('','MINSIZE', '10');
  DBMS_CONNECTION_POOL.ALTER_PARAM ('','MAXSIZE', '20');
end;
/
Einstellungen überprüfen ...
SQL> SELECT * FROM DBA_CPOOL_INFO;

CONNECTION_POOL
--------------------------------------------------------------------------------
STATUS              MINSIZE    MAXSIZE   INCRSIZE SESSION_CACHED_CURSORS
---------------- ---------- ---------- ---------- ----------------------
INACTIVITY_TIMEOUT MAX_THINK_TIME MAX_USE_SESSION MAX_LIFETIME_SESSION
------------------ -------------- --------------- --------------------
 NUM_CBROK MAXCONN_CBROK
---------- -------------
SYS_DEFAULT_CONNECTION_POOL
ACTIVE                   10         20          2                     20
               300            120          500000                86400
         1         40000

Um den Pool nun mit unserem node.js Programm zu nutzen, müssen nur die Verbindungsdaten angepasst werden. Übrigens: Das :POOLED kann man an jeden Oracle-Connection-String anhängen - der Database Resident Connection Pool lässt sich also auch mit Java, .NET oder SQL*Plus nutzen.
var fs = require("fs");
var ora = require("oracle");

var oradb = {
  hostname: "sccloud034.de.oracle.com",
  port:     1521,
  database: "pdb01.de.oracle.com:POOLED",
  user:     "scott",
  password: "tiger"
}

var dirname = process.argv[2];

fs.readdir(dirname, function (err, files) {
  if (err) {throw err;}
  files.forEach(function (file) {
    fs.readFile(dirname+"/"+file, 'utf-8', function (err, data) {
      ora.connect(oradb, function(err, connection) {
        if (err) {throw err;}
        connection.execute(
          "insert into document_table values (:1, :2)",
          [file, data],
          function (err, results) {
            if (err) {throw err;}
            console.log('"'+file+'" saved.');
            connection.close();
        });
      });
    });
  });
});
Nun wird das Programm durchlaufen - als DBA kann man die View V$CPOOL_STATS und so die Auslastung der Datenbank beobachten ...
SQL> SELECT num_open_servers, num_busy_servers, num_auth_servers, num_requests
  2  FROM V$CPOOL_STATS

NUM_OPEN_SERVERS NUM_BUSY_SERVERS NUM_AUTH_SERVERS NUM_REQUESTS
---------------- ---------------- ---------------- ------------
              15                9                1          799

Der Schlüssel zu skalierbaren node.js Skripten mit der Oracle-Datenbank liegt also tatsächlich in diesem etwas unscheinbaren Connection Pool. Ein node.js Skript sollte ihn auf jeden Fall verwenden - genau wie PHP.
Vorerst soll das genug sein - ich finde node.js nicht uninteressant; man kann es dank der Funktionsbibliothek sehr schön als Skripting Sprache einsetzen: In einem anderen Beispiel habe ich XML-Dateien nach JSON konvertiert und in die Datenbank geladen; im Vergleich zu diesen Skripten waren das nur wenige Codezeilen mehr ...
In this blog posting, I'd like write something about my first experiences with the Oracle database and node.js. This will not be a tutorial on how to install and configure node.js, and how to install new packages - there are plenty tutorials of this kind available in the internet. This posting will focus on how to deal with the Oracle database in node.js programs.
I like to describe node.js as "javascript on the server". It is based on Chrome's JavaScript Engine: a node.js script is being placed in a normal file and then executed by node.js - typically launched from the command line. The programming language is Javascript, node.js is extensible, provides a package manager (npm) and has a vibrant community which drives and develops the function library. Compared to other programming languages, there is a huge difference: Node.js is asynchronous, event driven and non-blocking for I/O bound functions; I'll go into more details during the blog posting.
To connect to the Oracle database, a program uses a driver - in the Java World this is JDBC, in the .NET World this is ODP.NET and so on. For node.js Oracle does not (yet) provide a driver - so we have to look what the community provides: And there is the module node-oracle by Joe Ferner, which is available from GitHub.
The download contains a README which pretty well describes the installation of the node-oracle module into an existing node.js environment. On my linux system this went smooth and without problems. After that we can author the first node.js program which does something with the Oracle database. So, let's select the EMP table and print out the results.
var oracle = require('oracle');

var connectData = {
  hostname: "sccloud034.de.oracle.com",
  port:     1521,
  database: "pdb01.de.oracle.com", 
  user:     "scott",
  password: "tiger"
}

oracle.connect(connectData, function(err, connection) {
  if (err) {
   console.log("Error connecting to db:", err); return;
  }

  connection.execute("select ename, job from emp ", [],  function(err, results) {
    connection.close();
    console.log(results);
  });
});

console.log("done");
As said earlier, node.js is event driven. The oracle.connect function, which opens the connection to the database, is I/O bound (network communication to the Oracle database). So node.js executes it asynchonously. During its execution, node.js does not block and continues working with the next statement. Upon finish, the oracle.connect will execute the callback function which has been provided as a parameter (in the example this is an anonymous function). So, node.js code looks different from Java, C or PHP code. Due to the asynchronous and non-blocking architecture, developers work with callback functions.
Upon execution, the script generates the following output
$ node ora.js
done
[ { ENAME: 'SMITH', JOB: 'CLERK' },
  { ENAME: 'ALLEN', JOB: 'SALESMAN' },
  { ENAME: 'WARD', JOB: 'SALESMAN' },
  { ENAME: 'JONES', JOB: 'MANAGER' },
  { ENAME: 'MARTIN', JOB: 'SALESMAN' },
  { ENAME: 'BLAKE', JOB: 'MANAGER' },
  { ENAME: 'CLARK', JOB: 'MANAGER' },
  { ENAME: 'SCOTT', JOB: 'ANALYST' },
  { ENAME: 'KING', JOB: 'PRESIDENT' },
  { ENAME: 'TURNER', JOB: 'SALESMAN' },
  { ENAME: 'ADAMS', JOB: 'CLERK' },
  { ENAME: 'JAMES', JOB: 'CLERK' },
  { ENAME: 'FORD', JOB: 'ANALYST' },
  { ENAME: 'MILLER', JOB: 'CLERK' } ]
$
console.log("done") is the very last statement within the script - but in the output it seems that it has been executed first. That is due to the non-blocking characteristics of node.js. If you examine the script carefully, you'll notice that at the top-level there are only 2 statements. The first is oracle.connect, the second is console.log. The other lines are callback functions. So the script starts by invoking oracle.connect, the database connection is being established - and while this is being done, node.js continues executing the console.log statement. So we first see "done" and then the actual data from the database.
The next node.js script is supposed to load files into the database. I want to provide a directory - the node.js script loads all text files within that directory into a given database table, DOCUMENT_TABLE.
create table document_table (filename varchar2(200), document clob);
The node.js script is based on the previous one: The nature of the task is a bit more complex - and so is the script. The filesystem calls for reading a directory and reading a file are I/O bound as well - and so they have the same characteristics as the Oracle calls. We need to provide a callback in all the cases. For that reason we get this highly nested code. There are approaches in the node.js community to keep the code more simple, but this is another topic.
var fs = require("fs");
var ora = require("oracle");

var oradb = {
  hostname: "sccloud034.de.oracle.com",
  port:     1521,
  database: "orcl",
  user:     "scott",
  password: "tiger"
}

var dirname = process.argv[2];

ora.connect(oradb, function(err, connection) {
  if (err) {throw err;}
  connection.setAutoCommit(false);
  var fileCount = 0;
  fs.readdir(dirname, function (err, files) {
    if (err) {throw err;}
    files.forEach(function (file) {
      fileCount ++;
      fs.readFile(dirname+"/"+file, 'utf-8', function (err, data) {
        connection.execute(
          "insert into document_table values (:1, :2)",
          [file, data],
          function (err, results) {
            if (err) {throw err;} else {
              console.log('"'+file+'" saved.');
              fileCount--;
              if (fileCount == 0) {
                connection.close();
                console.log("done");
              }
            }
        });
      });
    });
  });
});
The script opens the connection to the Oracle database, walks through the directory, reads each file and performs a SQL INSERT on the Oracle database. So far, so good. Here all the work is being done within one database connection. So on the database side, we utilize one CPU. Some database systems have more available resources, so what to do if we want to have this more scalable ...?
We need more database connections - so we change the order within the script. We first walk though the directory, read each file, then open a database connection in order to perform the INSERT operation. The code now looks like this.
var fs = require("fs");
var ora = require("oracle");

var oradb = {
  hostname: "sccloud034.de.oracle.com",
  port:     1521,
  database: "pdb01.de.oracle.com",
  user:     "scott",
  password: "tiger"
}

var dirname = process.argv[2];

fs.readdir(dirname, function (err, files) {
  if (err) {throw err;}
  files.forEach(function (file) {
    fs.readFile(dirname+"/"+file, 'utf-8', function (err, data) {
      ora.connect(oradb, function(err, connection) {
        if (err) {throw err;}
        connection.execute(
          "insert into document_table values (:1, :2)",
          [file, data],
          function (err, results) {
            if (err) {throw err;}
            console.log('"'+file+'" saved.');
            connection.close();
        });
      });
    });
  });
});
In the "traditional" world, this would work without any problems - perhaps it would be slower, because all these database connections are being opened and closed - but it would work. But the node.js script shows up nothing ... and after a while it stops with an error message (note that the script might run successful on a database with huge resources). What happens here ...?
[oracle@sccloud033 node]$ node loadFiles.js po

/home/oracle/node/loadFiles.js:19
          if (err) {throw err;}
                          ^
Error: ORA-12516: TNS:listener could not find available handler with matching protocol stack
Things become clear as we start monitoring the V$SESSION view ...
SQL> select username, count(*) from v$session group by username

USERNAME                         COUNT(*)
------------------------------ ----------
                                       28
SCOTT                                 154
SYS                                     1

-- after a while ...

SQL> select username, count(*) from v$session group by username

USERNAME                         COUNT(*)
------------------------------ ----------
                                       26
SCOTT                                 366
SYS                                     1

Again, node.js is event-driven. Creating an Oracle connection is a very expensive task - while the first one is running, the script continues in walking through the directory, reading files and spawning new Oracle connections. Before the first file has been stored into the database, node.js has walked completely though the directory and requested a database connection for each file. And as soon as the database limits have been reached, the script stops.
We need a connection pool. But node.js does not provide a connection pool for database connections. Luckily, the database does. Oracle 11.1 introduced the Database Resident Connection Pool which has been developed for exactly these cases. This connection pool (which is not the Shared Server Architecture) is a pool of Dedicated Server Connections. When a client establishes a database connection, no new background process will be created, it will be taken from the pool. And when the client closes the connection, the server process is not being destroyed, it is being placed back into the pool. And as all connection pools, one can configure settings like the minimum or maximum amount of connections or other settings.
The database-resident connection pool is being administered with the PL/SQL package DBMS_CONNECTION_POOL. You need DBA privileges in order to work with it and if you are using Oracle12c and the Multitenant Architecture, you need to work in the Container Database. Now, start the Connection Pool with default settings.
SQL> exec dbms_connection_pool.start_pool;

PL/SQL procedure successfully completed.
We can adjust pool settings ...
begin
  DBMS_CONNECTION_POOL.ALTER_PARAM ('','MINSIZE', '10');
  DBMS_CONNECTION_POOL.ALTER_PARAM ('','MAXSIZE', '20');
end;
/
... and check the existing configuration.
SQL> SELECT * FROM DBA_CPOOL_INFO;

CONNECTION_POOL
--------------------------------------------------------------------------------
STATUS              MINSIZE    MAXSIZE   INCRSIZE SESSION_CACHED_CURSORS
---------------- ---------- ---------- ---------- ----------------------
INACTIVITY_TIMEOUT MAX_THINK_TIME MAX_USE_SESSION MAX_LIFETIME_SESSION
------------------ -------------- --------------- --------------------
 NUM_CBROK MAXCONN_CBROK
---------- -------------
SYS_DEFAULT_CONNECTION_POOL
ACTIVE                   10         20          2                     20
               300            120          500000                86400
         1         40000

To actually use the connection pool in our node.js script, we just need to make a tiny change within the database connection parameters. Note that this works in SQL*Plus, Java or any other Oracle client as well.
var fs = require("fs");
var ora = require("oracle");

var oradb = {
  hostname: "sccloud034.de.oracle.com",
  port:     1521,
  database: "pdb01.de.oracle.com:POOLED",
  user:     "scott",
  password: "tiger"
}

var dirname = process.argv[2];

fs.readdir(dirname, function (err, files) {
  if (err) {throw err;}
  files.forEach(function (file) {
    fs.readFile(dirname+"/"+file, 'utf-8', function (err, data) {
      ora.connect(oradb, function(err, connection) {
        if (err) {throw err;}
        connection.execute(
          "insert into document_table values (:1, :2)",
          [file, data],
          function (err, results) {
            if (err) {throw err;}
            console.log('"'+file+'" saved.');
            connection.close();
        });
      });
    });
  });
});
While the node.js script is running, you might monitor the Oracle View V$CPOOL_STATS ... there you can see, how many server processes are being actually used.
SQL> SELECT num_open_servers, num_busy_servers, num_auth_servers, num_requests
  2  FROM V$CPOOL_STATS

NUM_OPEN_SERVERS NUM_BUSY_SERVERS NUM_AUTH_SERVERS NUM_REQUESTS
---------------- ---------------- ---------------- ------------
              15                9                1          799

The key to scalable node.js scripts working with the Oracle database is a mainly unkown database feature: Database Resident Connection Pool. Every node.js program working on the Oracle database should use it.
I did some further experiments with node.js - but for today this should be enough information. I think, node.js can be nicely used as a scripting language. For instance, converting a folder of XML documents to JSON and uploading this to the database is just a minor change within the above script and will lead to only a few more lines of code ...

1 Kommentar:

Anonym hat gesagt…

Sehr geehrter Herr Czarski,

Vielen Dank für den Artikel zu Node.
Oracle hatte Ende September einen
eigenen Treiber für Node angekündigt (oraclejs), dieser scheint aber auf GitHub z.Zt. noch nicht verfügbar zu sein.
Die mangelnde Qualität der Oracle-Treiber ist im Moment das größte Hinderniss, wenn man ernsthafte Node-Applikation schreiben will.

Mfg

Beliebte Postings