Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8957

PharoからOracle/MySQLに接続するnode.jsのapiサーバーを構築する

$
0
0
はじめに いままでSqueak4.4とPharo7でWebアプリサーバーを構築していましたが、DBXTalkのインストールが失敗するためOracleデータベースへの接続にはperlのDBI/DBDライブラリを利用していました。 ただし、perlを呼ぶOSProcessはWindowsでは動かないためLinux版Pharoでしか開発/テストが出来ず、WindowsPCで開発してLinuxサーバーで運用というスタイルが取れないのがこれまでの悩みでした。 今回Pharo8へのマイグレーションを行う際に、データベースへのアクセスをnode.jsに代行させるようにしたらすべて解決出来たので共有します。 ついでにMySQLの接続もサポートしました。 概念図 PharoでSeaside3をWebサーバーとして起動します。 node.jsはapiサーバーとして機能します(今回はWindows10PCに立てましたがWindowsでもLinuxでも好きな環境に立てて下さい) ソースコード node.js server.jsはサーバーとしてポート3000をリッスンして起動します。 運用環境ではpm2で自動起動するといいと思います。 server.js let restify = require("restify"); let server = restify.createServer(); server.use(restify.plugins.bodyParser()); const oracledb = require("oracledb"); const mysql = require("mysql"); const util = require("util"); let pool; const init = async () => { try { await oracledb.createPool({ user: "admin", password: "pass", connectString: "oracle.example.com/example", poolMax: 4, poolMin: 0 }); console.log("Connection pool started"); pool = mysql.createPool({ host: "localhost", user: "admin", password: "pass", timezone: "jst", multipleStatements: true }); } catch (err) { console.error("init() error: " + err.message); } } const execOracle = async (sql, binds, options) => { let connection; try { connection = await oracledb.getConnection(); const result = await connection.execute(sql, binds, options); return result; } catch (err) { console.error(err); } finally { if (connection) { try { await connection.close(); } catch (err) { console.error(err); } } } } const execMysql = async (request) => { pool.query = util.promisify(pool.query); try { const result = await pool.query(request); return result; } catch (err) { throw new Error(err); } } const closePoolAndExit = async () => { console.log("\nTerminating"); try { await oracledb.getPool().close(10); console.log("Pool closed"); pool.end(); process.exit(0); } catch (err) { console.error(err.message); process.exit(1); } } (async () => { try { server.post("/oracle", async (req, res, next) => { const request = JSON.parse(req.body.request); const sql = request.sql; const binds = request.binds; const options = request.options; const result = await execOracle(sql, binds, options); res.json(result); return next(); }); server.post("/mysql", async (req, res, next) => { const request = JSON.parse(req.body.request); const result = await execMysql8(request); res.json(result); return next(); }); process.once("SIGTERM", closePoolAndExit).once("SIGINT", closePoolAndExit); await init(); server.listen(process.env.PORT || 3000, function() { console.log("Server started."); }); } catch (err) { console.error(err); } })(); Smalltalkライブラリ Pharoに以下のライブラリをロードします SeasideとNeoJSONのインストール Metacello new baseline:'Seaside3'; repository: 'github://SeasideSt/Seaside:master/repository'; load. Gofer it smalltalkhubUser: 'SvenVanCaekenberghe' project: 'Neo'; configurationOf: 'NeoJSON'; loadStable. Pharo テストで使用したコードは以下の通りです。 実際に使う際にはラッパークラスを作って運用することになると思います。 Oracle接続テスト NeoJSONReader fromString: ( ZnClient new url: 'http://localhost:3000/oracle'; formAt: 'request' put: (NeoJSONWriter toString:( Dictionary new at: 'sql' put: 'SELECT * FROM hoge WHERE id=:1'; at: 'options' put: (Dictionary new at:'outFormat' put: 4002; yourself); at: 'binds' put: (Array with: 1); yourself )); post ). MySQLでもコネクションプールを使うので接続先のデータベースは都度選択する想定です。 MySQL接続テスト NeoJSONReader fromString: ( ZnClient new url: 'http://localhost:3000/mysql'; formAt: 'request' put: (NeoJSONWriter toString:( Dictionary new at: 'sql' put: 'use fuga; SELECT * FROM hoge WHERE id=?'; at: 'timeout' put: 40000; at: 'values' put: (Array with: 1); yourself )); post ). まとめ これで、WindowsPCで開発してLinuxサーバーで運用するスタイルが確立出来ました。 余談 PharoのLibCクラスのresultOfCommand:を使えばOSProcess同様にWindowsのコマンドが実行できるのがわかったので、最初はnode.jsのプログラムをPharoからLibCで呼び出すようにしましたが、Oracleデータの取得に1300ミリ秒(内データベース接続に900ミリ9秒)もかかってしまうため実用になりませんでした。 プログラムを毎回起動するとデータベース接続も毎回行われるため、コネクションプールを使う=サーバー化することで、データの取得が20ミリ秒に短縮出来ました。

Viewing all articles
Browse latest Browse all 8957

Trending Articles