LoginSignup
10

More than 5 years have passed since last update.

AWS Lambda (Node.js-v4.3.2)からOracleに接続する(ORA-21561への対応)

Last updated at Posted at 2016-10-04

ORA-21561の部分に関して2016/11/7に追記しています。

AWS Lambda(in VPC)からOracleに接続する時に数時間ハマったので記録として残しておきます

気付いてしまえばたいしたことないんですが、途中にある「ORA-21561: OID generation failed」のへの対応で全作業時間の9割程度なやんでいました

AWS Lambda (Node.js-v4.3.2)の実行環境に近いEC2環境の構築

AWS Lambda (Node.js-v4.3.2)の実行環境に近いEC2環境の構築を参考にしてください

Oracle InstantClientのインストール

Instant Client Downloads for Linux x86-64(要ログイン)からrpmをダウンロードします

必要なものは以下の2つです
oracle-instantclient12.1-basic-12.1.0.2.0-1.x86_64.rpm
oracle-instantclient12.1-devel-12.1.0.2.0-1.x86_64.rpm

ダウンロードしたらインストールします

terminal
$ sudo rpm -i oracle-instantclient12.1-basic-12.1.0.2.0-1.x86_64.rpm oracle-instantclient12.1-devel-12.1.0.2.0-1.x86_64.rpm

nodejsからOracleへの接続

接続するためのコードを書く

プロジェクトの作成とoracledbのインストール

terminal
$ mkdir oracletest
$ cd oracletest
$ npm init
$ npm install oracledb --save

テスト用コードの作成

process.env.NODE_ORACLEDB_* に関しては適宜書き換え・環境変数として渡すなどしてください
※接続用の環境変数は公式のテストコードを参考にしてます

index.js
'use strict';

process.env.NODE_ORACLEDB_USER='user'
process.env.NODE_ORACLEDB_PASSWORD='password'
process.env.NODE_ORACLEDB_CONNECTIONSTRING='hostname:port/servicename'

const oracledb = require('oracledb');

exports.handler = function(event, context, callback) {
  console.log('start');
  oracledb.getConnection({
    user : process.env.NODE_ORACLEDB_USER,
    password : process.env.NODE_ORACLEDB_PASSWORD,
    connectString : process.env.NODE_ORACLEDB_CONNECTIONSTRING,
  },
  function(err, connection) {
    if (err) { callback(err); return; }
    console.log('connected');
    connection.execute("SELECT * FROM [table] WHERE ROWNUM < 10", [], function(err, result) {
      if (err) { callback(err); return; }
      callback(null, result.rows);
    });
  });
}
test.js
'use strict';

const t = require('./index');
t.handler({}, {}, function(error, result){
  console.log(error);
  console.log(result);
});

実行

terminal
$ node test.js
start
[Error: ORA-21561: OID generation failed
]
undefined

ORA-21561: OID generation failedへの対応

2016/11/07追記 ここから
その後動作を確認したりいろいろしていたところ、「DHCP Options Sets」の設定の問題だと気付きました。
VPC内で独自でDNSサーバーを構築している関係で、デフォルトで設定されているはずの「domain-name = ap-northeast-1.compute.internal」を解除していたようです。
domain-nameを追加した設定を作成し、DHCP Options setに設定したところ、LOCALDOMAINの設定なしで動作することを確認できました。
2016/11/07追記 ここまで

ぐぐるとわかりますが、/etc/hostsを書き換えるのが標準的な対応のようです

今回は、AWS Lambdaのため設定ファイルに触れないのでどうしたらいいのか悩みました
問題は自ホストのホスト名が引けないことが原因なので以下の対応を行いました

  • VPCのDNS Hostnamesを有効してVPCローカルなドメインを自ホストに紐付ける
  • 環境変数(LOCALDOMAIN)を利用して検索対象のドメインを設定、上記のドメインを引けるようにする
LOCALDOMAIN='ap-northeast-1.compute.internal'

※ ap-northeast-1の部分はVPCのリージョンによって切り分ける必要があります
AWS Lambdaの環境変数を使えばリージョンごとの切り替えは自動にできそうです

コードはこのようになりました(3行目が追加されただけ)

index.js
'use strict';

process.env.LOCALDOMAIN='ap-northeast-1.compute.internal';
process.env.NODE_ORACLEDB_USER='user'
process.env.NODE_ORACLEDB_PASSWORD='password'
process.env.NODE_ORACLEDB_CONNECTIONSTRING='hostname:port/servicename'

const oracledb = require('oracledb');

exports.handler = function(event, context, callback) {
  console.log('start');
  oracledb.getConnection({
    user : process.env.NODE_ORACLEDB_USER,
    password : process.env.NODE_ORACLEDB_PASSWORD,
    connectString : process.env.NODE_ORACLEDB_CONNECTIONSTRING,
  },
  function(err, connection) {
    if (err) { callback(err); return; }
    console.log('connected');
    connection.execute("SELECT * FROM [table] WHERE ROWNUM < 10", [], function(err, result) {
      if (err) { callback(err); return; }
      callback(null, result.rows);
    });
  });
}

再実行

terminal
$ node test.js
start
connected
null
[ [ 1, 2, 3], [ 3, 4, 5] ]

Lambdaへのアップロード

まずはアップロード用にzipアーカイブを作成します

terminal
zip -r oracletest.zip package.json index.js node_modules/

実行結果

アップロードして実行すると以下のようなエラーが発生しました

LogOutput
START RequestId: c4365deb-89fc-11e6-a186-f96f2fe34754 Version: $LATEST
2016-10-04T06:35:52.219Z    c4365deb-89fc-11e6-a186-f96f2fe34754    start
2016-10-04T06:35:52.357Z    c4365deb-89fc-11e6-a186-f96f2fe34754    Error: libclntsh.so.12.1: cannot open shared object file: No such file or directory
    at Error (native)
    at Object.Module._extensions..node (module.js:434:18)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/var/task/node_modules/oracledb/lib/oracledb.js:35:19)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
END RequestId: c4365deb-89fc-11e6-a186-f96f2fe34754
REPORT RequestId: c4365deb-89fc-11e6-a186-f96f2fe34754  Duration: 187.52 ms Billed Duration: 200 ms     Memory Size: 128 MB Max Memory Used: 15 MB  
Process exited before completing request

OracleのSharedObjectのアップロード

アーカイブにsoファイルを含んでいないためだと思われるので、必要そうなものをピックアップして一緒にzipします

terminal
mkdir lib
cp /usr/lib/oracle/12.1/client64/lib/libclntsh.so.12.1 ./lib/
cp /usr/lib/oracle/12.1/client64/lib/libclntshcore.so.12.1 ./lib/
cp /usr/lib/oracle/12.1/client64/lib/libipc1.so ./lib/
cp /usr/lib/oracle/12.1/client64/lib/libmql1.so ./lib/
cp /usr/lib/oracle/12.1/client64/lib/libnnz12.so ./lib/
cp /usr/lib/oracle/12.1/client64/lib/libocci.so ./lib/
cp /usr/lib/oracle/12.1/client64/lib/libociei.so ./lib/
cp /usr/lib/oracle/12.1/client64/lib/libons.so ./lib/
cp /lib64/libaio.so.1 ./lib/

AWS Lambdaの環境変数を見るとわかりますが、LD_LIBRARY_PATHにプロジェクトのlibディレクトリが含まれているようなのでsoファイルをlibディレクトリ以下にコピーしています

Lambdaへの再アップロード

再アップロード用にzipファイルを作成します。

terminal
zip -r oracletest.zip package.json index.js node_modules/ lib/

最初のアップロードでは直接AWS Lambdaにアップロードできましたが、今回はsoファイルのを含むため、直接アップロード可能な50MBを超えています
そのため、今回はzipファイルをs3にアップロードし、AWS Lambda側ではそのリンクを指定してアップロードします

再実行結果

以上の対応で問題なくAWS Lambda(nodejs)からOracleへの接続ができるようになりました。
※ 再実行で出ていた取得したレコードはログではなく、AWS Lambdaの実行結果として返却されています

LogOutput
START RequestId: d6e7bac8-8a01-11e6-8fbc-1b17ce22866f Version: $LATEST
2016-10-04T07:12:01.578Z    d6e7bac8-8a01-11e6-8fbc-1b17ce22866f    start
2016-10-04T07:12:01.938Z    d6e7bac8-8a01-11e6-8fbc-1b17ce22866f    connected
END RequestId: d6e7bac8-8a01-11e6-8fbc-1b17ce22866f
REPORT RequestId: d6e7bac8-8a01-11e6-8fbc-1b17ce22866f  Duration: 389.55 ms Billed Duration: 400 ms 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10