この記事はテックタッチアドベントカレンダー15日目の記事です。
エンジニアの kenyu です。最近ウェブでもエッジコンピューティングが流行っていますね。AWS の Lambda@Edge や、ちょっと前に発表された Vercel の Edge Functions などなど、エッジでサーバサイドの処理をするのがトレンドになりつつあるのかなと感じています。
そこで気になるのは「RDB などのデータストアとどのように通信すればよいのか?」ということですが、先月 Cloudflare よりエッジから RDB に接続するためのソリューションが発表されました。
せっかくなのでどんな感じか試してみたいと思います!
引用元:Relational Database Connectorsのご紹介
イメージはこんな感じ。tunnel ごしに Worker と RDB がつながるイメージですね。
今回は Cloudflare Workers とローカルマシンを tunnel でつなぎ、エッジ上の Worker からローカルマシン上の PostgreSQL のデータを参照できるか試してみます。
下準備
無料独自ドメイン取得
Cloudflare のアカウントを新規作成するには独自ドメインが必要です。そこで無料で独自ドメインがとれる freenom を利用します。
"testtesttest.tk" のように、TLD まで指定しないと取得できないので注意。
- 参考 URL
Cloudflare
アカウントを作成し、取得した無料独自ドメインを使ってウェブサイトを追加します(nameserver を freenom で書き換えることを忘れずに)。
- 参考 URL
- https://tabikumo.com/wildcard-ssl-on-nas/#i-2 (現在と UI 違いますが参考になると思います。)
DB につなげてみる
https://developers.cloudflare.com/workers/tutorials/query-postgres-from-workers-using-database-connectors 上記を参考に設定していきますが、そのまま試してもうまくいかないところがあるので、以降うまくいった手順を書いていきます。
①tunnel
まずは Worker と PostgreSQL をつなぐ tunnel の準備です。
tunnel をつくるためには cloudflared を使う必要があるので、ダウンロードして下記のとおりログインします。
$ cloudflared tunnel login Please open the following URL and log in with your Cloudflare account: https://dash.cloudflare.com/argotunnel?callback=xxxxxx Leave cloudflared running to download the cert automatically.
上記 URL をクリックしてブラウザ上で認証します。
ドメインをクリックします。
Authorize をクリックします。
完了してターミナルに戻ると下記メッセージが出力されています。
You have successfully logged in. If you wish to copy your credentials to a server, they have been saved to: /home/xxxxxx/.cloudflared/cert.pem
credential ができているかチェック。ついでにディレクトリやファイルの権限を変えておきます(変えておかないと後述の PostgreSQL コンテナ起動時にエラーになります)。
$ ls -alh ~/.cloudflared total 12K drwx------ 2 xxxxxx xxxxxx 4.0K Dec 15 16:52 . drwxr-xr-x 22 xxxxxx xxxxxx 4.0K Dec 15 16:49 .. -rw------- 1 xxxxxx xxxxxx 1.9K Dec 15 16:52 cert.pem $ chmod 0777 ~/.cloudflared $ chmod 0644 ~/.cloudflared/cert.pem
②PostgreSQL
次は PostgreSQL です。tunnel のコンテナといっしょに立ち上げます。
$ cd ~/ $ git clone https://github.com/cloudflare/worker-template-postgres/ $ cd worker-template-postgres/scripts/postgres $ export TUNNEL_HOSTNAME=[Cloudflare に登録したウェブサイトのドメイン] $ docker compose up
起動したら一応別のターミナルでコンテナの起動状況を確認します。
$ docker compose ps WARN[0000] The "TUNNEL_HOSTNAME" variable is not set. Defaulting to a blank string. NAME COMMAND SERVICE STATUS PORTS postgres-cloudflared-1 "cloudflared --no-au…" cloudflared running postgres-pgbouncer-1 "/opt/bitnami/script…" pgbouncer running 6432/tcp postgres_postgresql_1 "/opt/bitnami/script…" postgresql running 5432/tcp
次にサンプルデータを投入します。
$ curl https://raw.githubusercontent.com/devrimgunduz/pagila/master/pagila-schema.sql | docker exec -i postgres_postgresql_1 psql -U postgres -d postgres $ curl https://raw.githubusercontent.com/devrimgunduz/pagila/master/pagila-data.sql | docker exec -i postgres_postgresql_1 psql -U postgres -d postgres
一応中身を確認してみます。
$ docker exec -it postgres_postgresql_1 psql postgres postgres psql (11.14) Type "help" for help. postgres=# \d List of relations Schema | Name | Type | Owner --------+----------------------------+----------+---------- public | actor | table | postgres public | actor_actor_id_seq | sequence | postgres public | actor_info | view | postgres . . . (41 rows) postgres=# select count(*) from actor; count ------- 200 (1 row) postgres=# \q
③Worker
最後に Worker です。
tunnel ごしに PostgreSQL へ接続するようにソースを一部書き換えます。
$ cd ~/worker-template-postgres $ vim src/index.ts
const client = new Client({ user: 'postgres', database: 'postgres', hostname: 'https://[Cloudflare に登録したウェブサイトのドメイン]', password: '', port: 5432, })
Client クラスは内部的に WebSocket を使って PostgreSQL に接続するドライバの一部です。このあたりを読むと詳しくわかります。
次に、ワーカーを動かすために wrangler をインストールしてログインします。
$ yarn global add @cloudflare/wrangler $ wrangler login Allow Wrangler to open a page in your browser? [y/n] y 💁 Opened a link in your default browser: https://dash.cloudflare.com/oauth2/auth?xxxxxx
認証画面で Allow をクリックします。
✨ Successfully configured. You can find your configuration file at: /home/xxxxxx/.wrangler/config/default.toml
Account ID を確認します。
$ wrangler whoami ╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ 👋 You are logged in with an OAuth Token, associated with the email xxxxxx@xxxxxx'! │ │ │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯ +-------------------------------+----------------------------------+ | Account Name | Account ID | +-------------------------------+----------------------------------+ | xxxxxxxx's Account | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | +-------------------------------+----------------------------------+
Account ID を設定ファイルに書きます。
$ cd ~/worker-template-postgres $ vim wrangler.toml
account_id = "[Account ID]"
publish します。
$ wrangler publish ⚡ Done in 11ms ✨ Build completed successfully! ✨ Successfully published your script to https://worker-template-postgres.xxxxxx.workers.dev
これで Worker がデプロイされました。
上記 URL を叩き、次のように表示されたら成功です。
ホントにつながりますね!すごい。
ちなみに docker compose up したターミナルで Ctrl+C して tunnel/PostgreSQL のコンテナを落としてから再度上記 URL を叩いてみると、以下のようになります。
tunnel がないとちゃんと(?)PostgreSQL に接続できなくなっています。 さらにちょっとクエリを修正して確認してみます。
src/index.ts
// Query the database. - const param = 42 const result = await client.queryObject< number - >`SELECT ${param} as answer;` + >`select count(*) as answer from actor;` // Return result from database. - return new Response(JSON.stringify(result.rows[0])) + return new Response( + JSON.stringify({ answer: result.rows[0]['answer'].toString() }), + )
修正後、再度 publish して結果を確認してみます。
やはりちゃんと PostgreSQL からデータを取得できていそうですね! Worker のスクリプトをいじってみたりして色々実験してみてください!
最後に
冒頭で「エッジでサーバサイドの処理をするのがトレンドになりつつあるのかな」と書きましたが、エッジコンピューティングが十分な効果を発揮する場面はある程度限られているかも?と考えています(グローバルなサービスなど)。あくまでひとつの武器として適切な場面で活用していけるといい技術だなと感じました。というわけで、これからも引き続きいろいろと試していきたいと思います!