Techtouch Developers Blog

テックタッチ株式会社の開発チームによるテックブログです

エッジ上の Cloudflare Workers で RDB からデータを取得してみる

f:id:techtouch:20211215203309p:plain

この記事はテックタッチアドベントカレンダー15日目の記事です。

エンジニアの kenyu です。最近ウェブでもエッジコンピューティングが流行っていますね。AWS の Lambda@Edge や、ちょっと前に発表された Vercel の Edge Functions などなど、エッジでサーバサイドの処理をするのがトレンドになりつつあるのかなと感じています。

そこで気になるのは「RDB などのデータストアとどのように通信すればよいのか?」ということですが、先月 Cloudflare よりエッジから RDB に接続するためのソリューションが発表されました。

せっかくなのでどんな感じか試してみたいと思います!

f:id:techtouch:20211215214143p:plain 引用元:Relational Database Connectorsのご紹介

イメージはこんな感じ。tunnel ごしに Worker と RDB がつながるイメージですね。

今回は Cloudflare Workers とローカルマシンを tunnel でつなぎ、エッジ上の Worker からローカルマシン上の PostgreSQL のデータを参照できるか試してみます。


下準備

無料独自ドメイン取得

Cloudflare のアカウントを新規作成するには独自ドメインが必要です。そこで無料で独自ドメインがとれる freenom を利用します。

https://my.freenom.com/

"testtesttest.tk" のように、TLD まで指定しないと取得できないので注意。

Cloudflare

アカウントを作成し、取得した無料独自ドメインを使ってウェブサイトを追加します(nameserver を freenom で書き換えることを忘れずに)。


DB につなげてみる

https://developers.cloudflare.com/workers/tutorials/query-postgres-from-workers-using-database-connectors 上記を参考に設定していきますが、そのまま試してもうまくいかないところがあるので、以降うまくいった手順を書いていきます。

①tunnel

f:id:techtouch:20211215214350p:plain

まずは 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 をクリックしてブラウザ上で認証します。

f:id:techtouch:20211215214619p:plain

ドメインをクリックします。

f:id:techtouch:20211215214634p:plain

Authorize をクリックします。

f:id:techtouch:20211215214648p:plain

完了してターミナルに戻ると下記メッセージが出力されています。

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

f:id:techtouch:20211215214422p:plain

次は 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

f:id:techtouch:20211215214444p:plain

最後に 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 を叩き、次のように表示されたら成功です。

f:id:techtouch:20211215214848p:plain

ホントにつながりますね!すごい。

ちなみに docker compose up したターミナルで Ctrl+C して tunnel/PostgreSQL のコンテナを落としてから再度上記 URL を叩いてみると、以下のようになります。

f:id:techtouch:20211215214907p:plain

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 して結果を確認してみます。

f:id:techtouch:20211216105505p:plain

やはりちゃんと PostgreSQL からデータを取得できていそうですね! Worker のスクリプトをいじってみたりして色々実験してみてください!


最後に

冒頭で「エッジでサーバサイドの処理をするのがトレンドになりつつあるのかな」と書きましたが、エッジコンピューティングが十分な効果を発揮する場面はある程度限られているかも?と考えています(グローバルなサービスなど)。あくまでひとつの武器として適切な場面で活用していけるといい技術だなと感じました。というわけで、これからも引き続きいろいろと試していきたいと思います!