このシリーズ記事ではFaaSからRDBMSへの接続パターンをハンズオン形式で解説しています。第一回はRDS Proxy、第二回はPrisma ORMを見てきました。
https://serverless.co.jp/blog/ee_1qfx155c6/
今日はData API / DataApp と TiDB Serverless Driver を見ていきます。
Data API とは
例えばAWSが提供している Aurora Data APIは、HTTPリクエストを介してAuroraデータベースにアクセスするためのAPIです。通常のデータベースへの接続はTCPベースで行われますが、DataAPIを用いるとHTTPベースへの接続に切り替えることができます。また過去記事で触れた接続管理の必要がない(AWSが基盤の一部としてコネクション管理を行います)ことからステートレス基盤であるLambdaからの呼び出しに相性がいいといえます。
認証方式はAWS Secret ManagerやAWS IAMと統合されパスワードを用いずデータベースへの接続が可能となるため、セキュリティの向上も期待できます。
データリクエストはデータベースエンジンが理解可能なSQL形式をJSONで投げ込み、レスポンスにもJSONが使われるため、データベースエンジンが異なったとしてもレスポンスを処理する部分は汎用化できるというメリットもあります。
TiDB DataApp とは
Aurora DataAPIはAWS専用ですが、TCPではなくHTTPベースでデータベースを呼び出せる仕組みというのはいくつかのデータベースエンジンに存在しており、時としてその名称が変わります。サーバレス型MySQL互換データベースとして昨今注目を集めているTiDB Serverlessがその代表格です。
TiDB Serverless ではDataAppという名前でREST API形式でのデータベース接続が可能となっています。Aurora DataAPIと同様にTCPではなくHTTPベースでのデータベース接続が可能となり、接続管理は基盤が行ってくれるのでアプリケーション側でコネクションプーリングの実装などが不要となります。
DataAppを使ったサンプルな以下のようなものです。
const axios = require('axios');
// TiDB DataAppのAPIエンドポイントURL
const apiEndpoint = 'https://your-tidb-dataapp-endpoint/query'; // 実際のURLに置き換えてください
// APIキーや認証情報が必要な場合(例: Bearerトークンを使用)
const apiToken = 'your-api-token'; // 実際のAPIトークンに置き換えてください
// 実行するSQLクエリ
const sqlQuery = 'SELECT * FROM your_table LIMIT 10'; // 実際のテーブル名とSQLクエリに置き換えてください
// REST APIリクエストを送信する関数
async function fetchData() {
try {
// APIリクエストの設定
const response = await axios.post(
apiEndpoint,
{
query: sqlQuery, // 実行するSQLクエリ
},
{
headers: {
'Authorization': `Bearer ${apiToken}`, // 必要な場合、APIトークンをヘッダーに追加
'Content-Type': 'application/json',
},
}
);
// クエリ結果を表示
console.log('Query Result:', response.data);
} catch (error) {
console.error('Error executing query:', error.message);
}
}
// データを取得
fetchData();
TiDB Serverless Driver
前回の記事で触れたPrisma/ORMなどを普段お使いの方はRESTfulでデータベースを操作することに慣れているかもしれませんが、MySQLドライバーなどをお使いの方からすると少し慣れるまではとっつきずらいかもしれません。
TiDB ServerlessにはMySQLドライバーと同じ感覚でDataAppを操作できるようにServerless Driverというものが提供されています。
DataAppの上位で動作しますので、従来のMySQLドライバーと異なりHTTP接続が可能でコネクションも基盤側で管理されるという特徴に加えて、JavaScript/TypeScript環境においてNode.jsが不要でありパッケージが非常に軽量に出来上がることも特徴です。
AWS LambdaはNode.js実行環境をフルにサポートしていますが、昨今軽量かつ高速であることから注目されているエッジFaaS基盤にはNode.jsのサポートが限定的なものが多くあります。なおかつTCPのアウトバウンド通信が許可されていない環境もあり、Serverless Driverはそのような環境で効果を発揮します。
データベースへのコネクションを管理する必要がなくなるという意味においてServerless DriverはNode.jsをフルにサポートしているAWS Lambda環境でも、TiDB 接続への便利なツールとして選択肢に入ってきます。
さっそくやってみる
https://docs.pingcap.com/ja/tidbcloud/serverless-driver/
TiDBのドキュメントにはエッジ環境へのサンプルのみが記載されていますが、Lambdaへの組み込みも簡単です。

ではやっていきます。TiDB Serverless clusterの起動はとても簡単です。
0. TiDB Cloud へのログインとClusterの起動
まずは以下のサイトへログインします。初回だとアカウント登録が求められますが区ジレットカードは不要です。
Create Cluster ボタンをクリックします。

全てデフォルトのままCreate をクリックする。

Clusterが起動したらConnectをクリックします。

Generate Passwordをクリックして接続用パスワードを生成しておきます。そしてConnection Stringをコピーしておきます。
この値は後でLambdaの環境変数に設定します。
1. Lambda の構築
まずはプロジェクトをイニシャライズします。
mkdir lambda-tidb
cd .\lambda-tidb\
npm init -y
次にサーバレスドライバーをインストールします。
npm install @tidbcloud/serverless
通常のNode.jsを用いた開発環境と異なり、node_modulesというフォルダはできているものの、Nodeモジュールはインストールされていないことがわかります。

Lambda用コードとしてindex.mjsを作成します。
import { connect } from "@tidbcloud/serverless";
export const handler = async (event) => {
try {
// TiDB Serverless に接続
const conn = connect({ url: process.env.DB_URL });
// クエリ実行
const result = await conn.execute("SHOW TABLES");
return {
statusCode: 200,
body: JSON.stringify(result),
headers: { "Content-Type": "application/json" }
};
} catch (error) {
return {
statusCode: 500,
body: JSON.stringify({ error: error.message })
};
}
};
2.デプロイとテスト
この状態でzipを作成しLambda関数にアップロードします。できあがったZIPは19KBとかなり軽量であることがわかります。


最後にTiDB Serverless クラスターへの接続文字列を環境変数に設定します。

テストを行えば`SHOW TABLES`が実行され以下のJSONが戻ります。
{
"statusCode": 200,
"body": "[{\"Tables_in_test\":\"categories\"},{\"Tables_in_test\":\"products\"},{\"Tables_in_test\":\"products_nofk\"},{\"Tables_in_test\":\"users\"}]",
"headers": {
"Content-Type": "application/json"
}
}
次回は第4回として、FaaS基盤からRDBMS接続における注意点と接続パターン Amazon RDS Aurora Serverless DataAPIの紹介をしたいと思います。