Slide 1

Slide 1 text

1 Notionで作るWebサイト 「MuuMuu Sites」の裏側 きのすけ (⻄⽥ 貴之) ホスティング事業部 事業開発チーム 2023.12.13

Slide 2

Slide 2 text

2 ⾃⼰紹介 ホスティング事業部 事業開発チーム 2020年 中途⼊社 きのすけ kinosuke01 ● Webアプリケーションエンジニア ● バックエンドの開発がメインですが、 職種を越境してフルサイクルな動きをしがち。 ● ディレクターや デザイナーとわいわい仕事しています。 ● X(Twitter) : @kinosuke01

Slide 3

Slide 3 text

3 アジェンダ ● MuuMuu Sitesというサービスをリリースしました。 ● 新しいサービス、裏側の仕組み気になりますよね。 ● 今回は、そういった好奇⼼を少しでも満たせれば。

Slide 4

Slide 4 text

4 アジェンダ 1. MuuMuu Sites の 紹介 2. MuuMuu Sites の 設計 3. ⼯夫した点 3.1. jobの死活監視 3.2. サイト公開フロー

Slide 5

Slide 5 text

1. MuuMuu Sites の 紹介 5

Slide 6

Slide 6 text

MuuMuu Sites の 紹介 6 MuuMuu Sites ってなに? Notionに書いたページに 独⾃ドメインをあてて デザインをカスタマイズして Webサイトとして 公開できるサービス

Slide 7

Slide 7 text

MuuMuu Sites の 紹介 7 MuuMuu Sites ってなに? - 補⾜ ● ドメインの購⼊管理ができるサービス 「ムームードメイン」 の 1機能として提供 ● 必要な費⽤は「ドメインの取得更新費」のみ ドメインがあれば無料でサイトが作成可能 ● 読みは「ムームーサイト」

Slide 8

Slide 8 text

MuuMuu Sites の 紹介 8 1. ムームードメインでドメインを取得 2. Notionにコンテンツを書く 3. MuuMuu Sites でWebサイトを作成 使い⽅

Slide 9

Slide 9 text

MuuMuu Sites の 紹介 9 ● MuuMuu Sitesで案内に従って選択肢から選ぶだけ MuuMuu SitesでWebサイトを作成 ドメインを 選ぶ 公開する Notionページ を選ぶ サイトの テーマを選ぶ Notion連携 \!完成!/

Slide 10

Slide 10 text

MuuMuu Sites の 紹介 10 設定項⽬が厳選されているので、選択肢から選ぶだけで 「あ、これもいいな」と思えるサイトに。 デザインのカスタマイズ

Slide 11

Slide 11 text

2. MuuMuu Sites の 設計 11

Slide 12

Slide 12 text

MuuMuu Sites の 設計 12 Notion API ホスティングサーバ ページの情報を取得 取得したデータから サイトデータ (html,cssなど)を生成 生成したファイルを ホスティングサーバに アップロード Webサイトとして 閲覧できる

Slide 13

Slide 13 text

MuuMuu Sites の 設計 13 サイト公開フロー - 概略 ⼩さくて読めないので 次のスライド以降でわけて説明

Slide 14

Slide 14 text

14 MuuMuu Sites の 設計

Slide 15

Slide 15 text

15 MuuMuu Sites の 設計

Slide 16

Slide 16 text

16 MuuMuu Sites の 設計

Slide 17

Slide 17 text

17 MuuMuu Sites の 設計 サイト公開 - 概略 • サイト公開に⾄るまで、このフローを何回も繰り返し動かしている • たとえば • DNS設定とVirtualHostの設定 → 処理終了 → 再度動かす → http疎通チェック → NG → 処理終了 → 再度動かす → http疎通チェック → NG → 処理終了 → 再度動かす → http疎通チェック → OK → 証明書発⾏へ進む

Slide 18

Slide 18 text

MuuMuu Sites の 設計 18 サイト作成API - 概略 WebAPI Job

Slide 19

Slide 19 text

MuuMuu Sites の 設計 19 サイト作成API - 概略 WebAPI Job サイトビルド&デプロイ リクエスト

Slide 20

Slide 20 text

MuuMuu Sites の 設計 20 サイト作成API - 概略 WebAPI Job WebAPIで受けた ビルド&デプロイリクエストは RedisStreamsを流れます

Slide 21

Slide 21 text

MuuMuu Sites の 設計 21 サイト作成API - 概略 WebAPI Job メッセージを受け取ったら、 Next.jsアプリケーションを 外部コマンドで起動し、 静的サイトをビルドします。 Next.jsアプリケーションは 内部でNotionAPIを呼び出し ビルドに必要な情報を取得します。

Slide 22

Slide 22 text

MuuMuu Sites の 設計 22 サイト作成API - 概略 WebAPI Job ⽣成された静的サイトのファイルを、ホスティングサーバへデプロイします。

Slide 23

Slide 23 text

MuuMuu Sites の 設計 23 サイト作成API - 概略 WebAPI Job 新しいサイトのデプロイを検知したら、 ユーザにその案内を表⽰します。

Slide 24

Slide 24 text

3. ⼯夫した点 - jobの死活監視 24

Slide 25

Slide 25 text

⼯夫した点 25 ● WebAPIは、ヘルスチェック⽤のエンドポイント⽣やしておけば ● jobの場合は? ○ 「正常に動作している」という状態をどう表現する? ○ それをどのようにしてPod外から監視するか? jobの死活監視どうする?

Slide 26

Slide 26 text

⼯夫した点 26 ● 「正常に動作している」という状態をどう表現する? ○ jobは定期的にRedisStreamsからメッセージを読み取っている ○ 読み取る直前にRedisにホスト名をキーにした値をsetする (Heart Beatをsetする) ○ その値はTTLつきとする (たとえば180秒とか) ● 定期的な読み取りがストップしていた場合、HeatBeatが揮発する ● HeartBeatがある状態を正常、ない場合を異常と扱う jobの死活監視はこうした

Slide 27

Slide 27 text

⼯夫した点 27 ● それをどのようにしてPod外から監視するか? ○ jobと同じプロセス内でexpressでhttpサーバを起動 ○ ヘルスチェック⽤のエンドポイントを準備 ■ HeartBeatの有無によって、 レスポンスのステータスコードを変える(200 or 500) ● これを、k8sのDeploymentのLivenessの設定に⼊れておく jobの死活監視はこうした

Slide 28

Slide 28 text

3. ⼯夫した点 - サイト公開フロー 28

Slide 29

Slide 29 text

MuuMuu Sites の 設計 29 まず思い出してほしい - サイト公開フロー サイト公開に⾄るまで、このフロー を何回も繰り返し動かしている たとえば DNS設定とVirtualHostの設定 → 処理終了 → 再度動かす → http疎通チェック → NG → 処理終了 → 再度動かす → http疎通チェック → NG → 処理終了 → 再度動かす → http疎通チェック → OK → 証明書発⾏へ進む

Slide 30

Slide 30 text

⼯夫した点 30 ● サイト公開フローは5分に1回のバッチ処理で実⾏している ● しかしそれだと無駄が多い側⾯がある ○ 例)サーバ証明書の発⾏リクエストが実⾏ → 1分後にhttps疎通できるようになった → でも、https疎通チェックと次のアクションの実⾏は4分後... この4分間無駄に待たされるのはどうなの? サイト公開フローをいい感じに連投したい - 課題

Slide 31

Slide 31 text

⼯夫した点 31 ● バッチ処理とは別ラインで、サイト公開処理を実⾏するようにした ● 「MuuMuu Sites」のコンパネ開きっぱなしのとき、 定期的(⼗数秒おき)にXHRで公開処理を実⾏するAPIを叩いている。 ● これにより、5分を待たずとも公開処理を先に進めることができている。 (※他にもやりようはあったのだけど、諸般の事情でそうした) サイト公開フローをいい感じに連投したい - こうしてみた

Slide 32

Slide 32 text

⼯夫した点 32 ● もちろんそうすることで新たな問題も。 ● 同じサイトの公開処理が並列で実⾏されうるので、 レースコンディション発⽣による、データの不整合など発⽣しないか。 レースコンディション - 新たな問題

Slide 33

Slide 33 text

⼯夫した点 33 ● シンプルに排他制御を設けて対応。 ○ 公開処理を実⾏する前に、サイト単位で公開処理をロックする。 ○ ロック中に他のプロセスがサイトの公開処理を実⾏した場合、 何もせずに終了する。 ○ 公開処理が終了したらロック解除。 ● 排他制御はDBを⽤いて実現。 レースコンディション - こう対応した

Slide 34

Slide 34 text

⼯夫した点 34 レースコンディション - こう対応した ロック処理の実装 (をかなり簡略化したもの)

Slide 35

Slide 35 text

⼯夫した点 35 ● ポイント: Transaction内でREAD時にレコードロックをかけることで、 ロック処理⾃体のレースコンディションも防⽌している。 レースコンディション - こう対応した

Slide 36

Slide 36 text

⼯夫した点 36 Transactionとロック読み取りがないと、こんなケースがありうる レースコンディション - こう対応した プロセスA (バッチ) プロセスB (XHR) muu_sites_publish_processes レコードを取得 muu_sites_publish_processes レコードを取得 is_locked == 0 だから ロックかかってないと判断し処理継続 is_locked == 0 だから ロックかかってないと判断し処理継続 is_locked = 1 として更新(=ロックする) メイン処理を実⾏ is_locked = 1 として更新(=ロックする) メイン処理を実⾏してしまう

Slide 37

Slide 37 text

⼯夫した点 37 Transactionとロック読み取りがあると安⼼ レースコンディション - こう対応した プロセスA (バッチ) プロセスB (XHR) トランザクション開始 トランザクション開始 muu_sites_publish_processes レコードを取得 ([DB]ロック読み取り) is_locked == 0 だから [APP]ロックかかってないと判断し処理継続 is_locked = 1 として更新(=[APP]ロックする) トランザクション終了 メインの処理を実⾏ muu_sites_publish_processes レコードを取得 is_locked == 1 なので[APP]ロックありと判断 トランザクション終了 [APP]ロックありなので、メイン処理はスキップ Aのトランザクション内で [DB]レコードロックがかけられているので、 Aのトランザクションが終了するまで 取得できない

Slide 38

Slide 38 text

まとめ 38

Slide 39

Slide 39 text

まとめ 39 みなさんの好奇⼼を多少満たすことは できたでしょうか。 サービスに興味がありましたら、 ぜひ「ムームーサイト」で 検索してみてください。

Slide 40

Slide 40 text

40 ありがとうございました!