Slide 1

Slide 1 text

Cloudflare Workers から PostgreSQL に接続可能になったので 試してみた 第 43 回 PostgreSQL アンカンファレンス@オンライン  2023/8/7 まつひさ(hmatsu47)

Slide 2

Slide 2 text

自己紹介 松久裕保(@hmatsu47) ● https://qiita.com/hmatsu47 ● 現在のステータス: ○ 名古屋で Web インフラのお守り係をしています ○ 現在は自社サービスのセキュリティ強化中 ○ ついでに MySQL HeatWave をのんびり検証中 ○ #pgunconf ゆるふわ勢 2

Slide 3

Slide 3 text

本日のネタ ● Cloudflare Workers、TCP ソケットで作成可能な connect()API を発表 https://www.infoq.com/jp/news/2023/07/cloudflare-workers-connect-api/ 3

Slide 4

Slide 4 text

本日のネタ ● Connect to databases(Cloudflare Docs) https://developers.cloudflare.com/workers/databases/connecting-to-databases/ ● Connect to PostgreSQL (beta)(Cloudflare Docs) https://developers.cloudflare.com/workers/databases/connect-to-postgres/ ※まだベータリリースなので使い方が予告なく変わる可能性があります 4

Slide 5

Slide 5 text

Cloudflare Workers とは? ● Cloudflare の一般的なイメージ ○ CDN ● Cloudflare 自身が表現する事業のコアドメイン ○ ウェブサイトのセキュリティーとパフォーマンス改善 ● Cloudflare Workers ○ エッジロケーションのサーバーレス環境 ○ ユーザーに近い場所でサーバーサイド JS を実行(SSR など) 5

Slide 6

Slide 6 text

Cloudflare Workers とは? ● Cloudflare の一般的なイメージ ○ CDN ● Cloudflare 自身が表現する事業のコアドメイン ○ ウェブサイトのセキュリティーとパフォーマンス改善 ● Cloudflare Workers ○ エッジロケーションのサーバーレス環境 ○ ユーザーに近い場所でサーバーサイド JS を実行(SSR など) 6

Slide 7

Slide 7 text

余談:最近の CDN ● エッジロケーションのサーバーレス環境は当たり前に ○ AWS : Lambda@Edge・CloudFront Functions ○ Fastly : Compute@Edge ○ Akamai : EdgeWorkers 7

Slide 8

Slide 8 text

Cloudflare Workers に connect()API が実装された ● 何ができる? ○ Workers から直接 TCP ベースの接続が可能 ■ 従来は HTTP(S) ベースか Cloudflare 内のサービスの接続のみ可能 ● Cloudflare 外のデータベースへの接続が可能に ○ PostgreSQL(TCP:5432)の外部データベース接続をサポート ■ node-postgres(pg)を使用 ■ ポート番号自体は変更可能 8

Slide 9

Slide 9 text

やってみた ● 前掲「Connect to PostgreSQL (beta)」のサンプル ○ RNAcentral の「Public Postgres database」に接続 RNAcentral: The non-coding RNA sequence database https://rnacentral.org/help/public-database 9

Slide 10

Slide 10 text

0. 事前準備 ● 詳細は省略します ○ Cloudflare にサインアップ ○ Node.js 16.13.0 以降と npm・Wrangler をインストール ○ Cloudflare dashboard で Worker を作成 ○ Worker project を TypeScript で作成 ○ node-postgres(pg)8.11.0 以降をインストール ■ npm・yarn などで pg と @types/pg をインストール 10

Slide 11

Slide 11 text

1. DB 接続用の環境変数をセット ● 秘匿する情報は secret にセット ○ 例) ● それ以外は wrangler.toml の [vars] に記述 ○ 例) 11 [vars] DB_USERNAME = "postgres" # Set your password by creating a Secret so it is not stored as plain text DB_HOST = "ep-aged-sound-175961.us-east-2.aws.neon.tech" DB_PORT = "5432" DB_NAME = "neondb" wrangler secret put DB_PASSWORD

Slide 12

Slide 12 text

1. DB 接続用の環境変数をセット ● 今回は公開情報なので wrangler.toml に DB_URL を記述 ※今回のサンプルはこちらの GitHub リポジトリにあります https://github.com/hmatsu47/cloudflare-workers-pg-connect 12 name = "pg-test" main = "src/index.ts" compatibility_date = "2023-08-01" # Ensure you enable Node.js compatibility to your project node_compat = true [vars] DB_URL = "postgres://reader:[email protected]:5432/pfmegrnargs"

Slide 13

Slide 13 text

2. コードを記述 13 import { Client } from 'pg'; export interface Env { DB_URL: string; } export default { async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise { const url = new URL(request.url); if (url.pathname === '/favicon.ico') return new Response(null, { status: 404 }); const client = new Client(env.DB_URL); await client.connect(); // Query the RNA database! const result = await client.query({ text: 'SELECT * FROM rnc_database LIMIT 10', }); console.log(JSON.stringify(result.rows)); const resp = Response.json(result.rows); // Clean up the client, ensuring we don't kill the worker before that is completed. ctx.waitUntil(client.end()); return resp; }, };

Slide 14

Slide 14 text

2. コードを記述 ● 個別のパラメーターを指定する場合 ○ 例) 14 // 環境変数取得用interface部分 export interface Env { DB_USERNAME: string; DB_PASSWORD: string; DB_HOST: string; DB_PORT: number; DB_NAME: string; } // 接続パラメーター指定部分 const client = new Client({ user: env.DB_USERNAME, password: env.DB_PASSWORD, host: env.DB_HOST, port: env.DB_PORT, database: env.DB_NAME }) // TLS接続はこちらを参照 // https://developers.cloudflare.com/workers/databases/connect-to-postgres/#ssl-modes

Slide 15

Slide 15 text

3. Cloudflare Workers にデプロイ 15 npx wrangler deploy ⛅ wrangler 3.4.0 ------------------ ▲ [WARNING] Enabling Node.js compatibility mode for built-ins and globals. This is experimental and has serious tradeoffs. Please see https://github.com/ionic-team/rollup-plugin-node-polyfills/ for more details. Your worker has access to the following bindings: - Vars: - DB_URL: "postgres://reader:NWDMCE5xdipIjRrp@hh..." Total Upload: 352.86 KiB / gzip: 70.51 KiB Uploaded pg-test (1.40 sec) Published pg-test (0.40 sec) https://pg-test.【アカウント名】.workers.dev ←デプロイ先のURL Current Deployment ID: ********-****-****-****-************

Slide 16

Slide 16 text

4. 動作確認 16 curl 【デプロイ先のURL】 | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 3116 100 3116 0 0 766 0 0:00:04 0:00:04 --:--:-- 780 [ { "id": "5", "timestamp": "2017-05-17T00:00:00.000Z", "userstamp": "RNACEN", "descr": "VEGA", "current_release": 98, "full_descr": "VEGA", "alive": "N", "for_release": null, "display_name": "VEGA", "project_id": "PRJEB4568", "avg_length": null, "min_length": null, "max_length": null, "num_sequences": "0", "num_organisms": "0" }, (後略)

Slide 17

Slide 17 text

デモ(時間があれば) ● SQL 文を書き換えて再デプロイしてみます 17

Slide 18

Slide 18 text

注意事項 ● Cloudflare Workers には実行時間制限がある ○ 無料プラン(リクエストあたり)CPU 時間:10 ミリ秒 ○ 有料プラン(同上)実時間:30 秒 ■ CPU 時間≠実時間(実際の実行時間) ■ CPU 時間に DB からのレスポンス待ち 時間は含まない模様 https://www.cloudflare.com/ja-jp/plans/developer-platform/ 18

Slide 19

Slide 19 text

注意事項 ● 処理が遅いとエッジロケーションで実行する意味がない ○ おそらく DB から取得したデータをキャッシュすることになる? ■ KV や Durable Objects に入れる? ■ ものによっては D1(エッジロケーションの分散 SQLite)に入れる? https://www.publickey1.jp/blog/23/cloudflaresqlitecloudflare_d110.html ● DB のアクセス許可範囲を正しく設定する ○ DB をパブリック IP アドレスで公開する必要があるので 19

Slide 20

Slide 20 text

まとめ ● Cloudflare Workers:エッジロケーション JS 実行環境 ● Cloudflare Workers が connect()API を実装 ● PostgreSQL への接続がサポートされたのでやってみた ● Workers には実行時間制限がある点に注意 ● データ取得後のキャッシュ戦略が重要になりそう ● DB のセキュリティ設定に気を付けるべし 20