Slide 1

Slide 1 text

Workers Tech Talks in Osaka #1 2024/02/26 Honoと PostgreSQL with Workersを 本番投⼊に向けて検証している話

Slide 2

Slide 2 text

⾃⼰紹介 株式会社アイデミー・エンジニア Kosuke Horai 良さげなライブラリを⾒つけたらWeb Standards Compatibleかを調べるのが最近の趣味 安価かつ楽にそれなりのスケールができるプラッ トフォームで開発するのが好き

Slide 3

Slide 3 text

⽬次 Chapter 1 Chapter 2 Chapter 3 なぜWorkersを使うのか 制約と必要なピース Workersの制約 必要なピース 遭遇する問題 node compatibility contextの引き回し connection pooling Chapter 4 Chapter 5 Chapter 6 実装のtipsや解決策 DB関連サービス AsyncLocalStorage パフォーマンス検証 CloudSQL HyperDrive Supabase Neon 今後の展望

Slide 4

Slide 4 text

なぜWorkersを使うのか Chapter 1

Slide 5

Slide 5 text

• TypeScriptが好き • 極⼒インフラを触りたくない • アプリケーションを書くことに集中したい! アプリケーションを書くことに集中したい なぜWorkersを使うのか

Slide 6

Slide 6 text

• Paid Planでも$5〜 • $0.02/100万[CPU ms] • $0.3/100万[req] • コールドスタートもほぼ 意識しなくてよい すごい安いうえにコールドスタートもほとんどない なぜWorkersを使うのか https://developers.cloudflare.com/workers/platform/pricing/

Slide 7

Slide 7 text

• TypeScriptしか書かないのでDockerすら⾯倒 • 退屈なビルド待ちの時間が短縮されるのが本当によい • ただ単純にTypeScriptを書く以外何も考えたくない Cloud Runでいいのでは? なぜWorkersを使うのか

Slide 8

Slide 8 text

制約と必要なピース Chapter 2

Slide 9

Slide 9 text

• CPU Time(Standard pricing) • Max of 30 seconds of CPU time per invocation • Max of 15 minutes of CPU time per Cron Trigger or Queue Consumer invocation • Node.jsの全てのAPIが使えるわけではない • Cloudflare Workers uses the V8 JavaScript engine from Google Chrome • 例えばfsは使えない Cloudflare Workersにおける制約 制約と必要なピース

Slide 10

Slide 10 text

• CPU Time(Standard pricing) • 外部との通信は含まれない • 普通のapiで30秒は⼗分だし、CronやQueueでのバッチも15分あれば適切 に切り分けて実⾏すればよいのでは • Node.jsの全てのAPIが使えるわけではない • とはいえ回避可能なことが多い • コミュニティの盛り上がりによるエコシステムの充実も感じる • 例: Firebaseなどのjwtの取り扱いはWeb Standards APIのみで組むのは⼀苦労だけど Code-Hex/firebase-auth-cloudflare-workers のお陰で楽に回避可能 Cloudflare Workersにおける制約 制約と必要なピース

Slide 11

Slide 11 text

Cloudflare Workers周辺技術 • Workers/Pages, Pub/Sub, Queues, KV, R2(Object Storage), Stream, Images… • Zero Trust, Load Balancing, WAF… 制約と必要なピース 基本的なWebアプリケーションに 必要な技術は揃っているのではないか

Slide 12

Slide 12 text

• 2023年5⽉頃、Workersから直接TCP接続が可能になった • 倒すべきはステートレスな環境におけるDBの取り扱いのみ 残る課題はDatabase接続 制約と必要なピース

Slide 13

Slide 13 text

遭遇する問題 Chapter 3

Slide 14

Slide 14 text

遭遇する問題 • 新しいフラグ • AsyncLocalStorageが使える • pg (node-postgres)が使えない • 旧来のフラグ • globalThisが使える • pg (node-postgres)が使える → Postgres.js(porsager/postgres)でnodejs_compatに寄せることが可能 https://github.com/cloudflare/workers-sdk/issues/4082 nodejs_compat vs node_compat お気持ち: ロギングなどにAsyncLocalStorageを活⽤していきたい。今後もnodeの互換性に関する実装はnodejs_compatの⽅が進みそう。新しい⽅を使いたい。

Slide 15

Slide 15 text

Contextの引き回し 遭遇する問題 環境変数は c.env.DATABASE_URL を引き回す必要がある workaroundは後述

Slide 16

Slide 16 text

ステートレス環境におけるconnection pooling • Workersは基本的にステートレス • ただし、DB clientはsingleton instanceを引き回す想定が多い • (PrismaやKyselyのdocumentに記載されている) 遭遇する問題 kyselyのdocumentより https://kysely.dev/docs/getting-started#instantiation

Slide 17

Slide 17 text

ステートレス環境におけるconnection pooling 遭遇する問題 wrangler devではエラーになる wrangler dev --remoteだと動く

Slide 18

Slide 18 text

ステートレス環境におけるconnection pooling • Workersは基本的に ステートレス • 実際には⼿元で数回試すと 最後のrequestから30秒近 く残っていそう 遭遇する問題 基本的にはletを使い回す書き⽅は良くなさそう

Slide 19

Slide 19 text

実装のtipsや解決策 Chapter 4 検証中でもっと良いやり⽅があるかもしれないことや良くない⽅法の可能性があることご了承ください。 あくまで私が考えた現状取れそうな実装上のtipsです。

Slide 20

Slide 20 text

Connection poolはDatabase側に任せる Serverless環境で利⽤しやすいDatabaseサービス • Hyperdrive(Connection Poolingとクエリキャッシュのみで別途Databaseは必要) • WorkersがPaid PlanであればConnection Poolingは無料 • PostgreSQLであれば基本的に使える(2024/02現在) • Supabase • supabase/supavisorによってConnection Poolingの対応できる • Neon • ただし⽇本リージョンがなくレイテンシーが無視できない ⼿元では単純なクエリを1回実⾏するだけでも500ms以上かかった(TCP接続) 実装のtipsや解決策

Slide 21

Slide 21 text

AsyncLocalStorageを活⽤する 実装のtipsや解決策 • compatibility_flags = [ "nodejs_compat" ] で使える • Request単位でmemory safeで⼀意なインスタンスを作成可能 • AsyncLocalStorageによりglobalなinstanceを代⽤する

Slide 22

Slide 22 text

AsyncLocalStorageを活⽤する 実装のtipsや解決策 Thanks to: https://github.com/yusukebe/async-local-storage-middleware/

Slide 23

Slide 23 text

AsyncLocalStorageを活⽤する 実装のtipsや解決策 Thanks to: https://github.com/yusukebe/async-local-storage-middleware/ • request全体で利⽤できるように AsyncLocalStorageをmiddleware で作成

Slide 24

Slide 24 text

AsyncLocalStorageを活⽤する 実装のtipsや解決策 • getSQL() がどこからでも呼 べるようになる • c.envを引き回す必要がない • transactionも同じインスタ ンスを使うので可能

Slide 25

Slide 25 text

パフォーマンス検証 Chapter 5

Slide 26

Slide 26 text

先に結論 パフォーマンス検証 • Supabaseが速くてConnection Poolもやってくれてよい • Hyperdriveもクエリキャッシュありだとよい

Slide 27

Slide 27 text

調査⽅法 パフォーマンス検証 • データはNeonが提⽰しているサンプルデータPeriodic table data • 1table, 118 Records, source file size 17KB • 1リクエスト内で50件取得するselect⽂を5回実⾏ • performance.now()によりそのクエリ部分の時間を記録 • クエリ `SELECT * FROM periodic_table limit 50` • リクエストは2回続けて⾏い、初回と2回⽬を記録 • PostgreSQL clientは Postgres.js(porsager/postgres) • 調査対象は下記 • Cloud SQL(Tokyo), Hyperdrive + Cloud SQL(Tokyo), Neon(Singapore), Supabase(Tokyo)

Slide 28

Slide 28 text

調査結果 パフォーマンス検証 Supabase Cloud SQL Hyperdrive (Cache無効) Hyperdrive (Cache有効) Neon 初回 2回⽬ 初回 2回⽬ 初回 2回⽬ 初回 2回⽬ 初回 2回⽬ 1 102ms 81ms 79ms 72ms 974ms 400ms 325ms 91ms 1537ms 775ms 2 16ms 15ms 11ms 11ms 375ms 326ms 53ms 63ms 86ms 84ms 3 16ms 16ms 12ms 11ms 432ms 324ms 58ms 62ms 86ms 84ms 4 22ms 15ms 11ms 11ms 414ms 325ms 64ms 62ms 87ms 85ms 5 16ms 15ms 11ms 11ms 327ms 325ms 37ms 62ms 86ms 84ms

Slide 29

Slide 29 text

調査結果 パフォーマンス検証 • 初回リクエスト、初回クエリは接続にオーバーヘッドがある Supabase Cloud SQL Hyperdrive (Cache無効) Hyperdrive (Cache有効) Neon 初回 2回⽬ 初回 2回⽬ 初回 2回⽬ 初回 2回⽬ 初回 2回⽬ 1 102ms 81ms 79ms 72ms 974ms 400ms 325ms 91ms 1537ms 775ms 2 16ms 15ms 11ms 11ms 375ms 326ms 53ms 63ms 86ms 84ms 3 16ms 16ms 12ms 11ms 432ms 324ms 58ms 62ms 86ms 84ms 4 22ms 15ms 11ms 11ms 414ms 325ms 64ms 62ms 87ms 85ms 5 16ms 15ms 11ms 11ms 327ms 325ms 37ms 62ms 86ms 84ms 所感: Cloud SQLのみ Connection Poolの仕組みはないことにより初回と2回⽬があまり変わらないのかもしれない

Slide 30

Slide 30 text

調査結果 パフォーマンス検証 • SupabaseとCloud SQLが速い Supabase Cloud SQL Hyperdrive (Cache無効) Hyperdrive (Cache有効) Neon 初回 2回⽬ 初回 2回⽬ 初回 2回⽬ 初回 2回⽬ 初回 2回⽬ 1 102ms 81ms 79ms 72ms 974ms 400ms 325ms 91ms 1537ms 775ms 2 16ms 15ms 11ms 11ms 375ms 326ms 53ms 63ms 86ms 84ms 3 16ms 16ms 12ms 11ms 432ms 324ms 58ms 62ms 86ms 84ms 4 22ms 15ms 11ms 11ms 414ms 325ms 64ms 62ms 87ms 85ms 5 16ms 15ms 11ms 11ms 327ms 325ms 37ms 62ms 86ms 84ms

Slide 31

Slide 31 text

調査結果 パフォーマンス検証 • Hyperdriveもクエリキャッシュが有効であれば速い 所感: 1つのworkersでHyperdriveのクエリキャッシュ有効/無効の2接続を使い分けるといいかもしれない(共存可能) Supabase Cloud SQL Hyperdrive (Cache無効) Hyperdrive (Cache有効) Neon 初回 2回⽬ 初回 2回⽬ 初回 2回⽬ 初回 2回⽬ 初回 2回⽬ 1 102ms 81ms 79ms 72ms 974ms 400ms 325ms 91ms 1537ms 775ms 2 16ms 15ms 11ms 11ms 375ms 326ms 53ms 63ms 86ms 84ms 3 16ms 16ms 12ms 11ms 432ms 324ms 58ms 62ms 86ms 84ms 4 22ms 15ms 11ms 11ms 414ms 325ms 64ms 62ms 87ms 85ms 5 16ms 15ms 11ms 11ms 327ms 325ms 37ms 62ms 86ms 84ms

Slide 32

Slide 32 text

所感 パフォーマンス検証 • Supabaseが速くてConnection Poolもやってくれてよい(再掲) • Hyperdriveも検討したい • Cloud SQLもよいがConnection Pooling問題を気にする必要がある • 1 request 1 connectionになるので同時接続数が気になる • c.executionCtx.waitUntil(client.end())を確実に呼んだり • 個⼈的にはNeonに期待してたけど⽇本regionが...... • CloudflareのHyperdrive発表記事でもNeonが最初に⾔及されていた > Hyperdrive works not only with PostgreSQL databases ̶ including Neon, Google Cloud SQL, AWS RDS......

Slide 33

Slide 33 text

今後の展望 Chapter 5

Slide 34

Slide 34 text

Hyperdriveに期待したい 今後の展望 • 接続をprivate network上に構築する課題が残っている • CloudflareのDiscordではroadmapとして、Hyperdriveがealy 2024に private networksの接続をサポートすると2023/09/28に⾔及されている > Support for databases in private networks (Magic WAN, Cloudflare Tunnels) in early 2024. • 引き続き検証進めつつproductionにのせていきたい • 最悪、Honoを使っているのでCloud Runにする⼿段も簡単なはず

Slide 35

Slide 35 text

Appendix

Slide 36

Slide 36 text

• 今回の発表に関するコード • https://github.com/pensuke81/workers-playground Appendix

Slide 37

Slide 37 text

参考⽂献

Slide 38

Slide 38 text

• JavaScript Containers • https://tinyclouds.org/javascript_containers • Hyperdrive試してみた🛸 • https://speakerdeck.com/aiji42/hyperdriveshi-sitemita • Workers & Pages Pricing • https://www.cloudflare.com/plans/developer-platform-pricing/ • AsyncLocalStorage | Node.js v21.6.2 Documentation • https://nodejs.org/api/async_context.html#class-asynclocalstorage • Neon Sample Data • https://github.com/neondatabase/postgres-sample- dbs/blob/f6c2e24910e9a1eb9c11c69628544d4d60d42e47/periodic_table.sql 参考⽂献

Slide 39

Slide 39 text

• Hyperdrive: making databases feel like theyʼre global • https://blog.cloudflare.com/hyperdrive-making-regional-databases- feel-distributed • Hyperdriveのprivate network接続のサポートに関する⾔及 • https://discord.com/channels/595317990191398933/11505579862390 21106/1156944940086083704 参考⽂献