本日のテーマ
環境構築がひと段落したところで、CMSの全体像を整理し、なぜこのサービス分割したのかを解説します。
全体アーキテクチャ(概要のみ)
- Frontend(Next.js)
- Auth Service(Go)
- Core API(C#)
- Publisher(Rails)
- Upload Service(Rails)
- AI Gateway(Rust)
- Observability(Grafana/Prometheus/Loki)
サービス一覧と役割
Frontend(Next.js / TypeScript)
- Markdownエディタ
- 認証UI
- 公開サイト(ISR対応)
Auth Service(Go)
- Auth0連携
- JWT発行
- WebAuthnパスキー認証
Core API(C#)
- 記事CRUD
- バージョン履歴管理
- Scheduler
- OutboxテーブルでQueue前段を実装
Publisher Service(Rails)
- 外部媒体(Zenn/Qiita/はてな)への投稿
- Sidekiqによる非同期ジョブ
- 投稿結果のCallback
Upload Service(Rails)
- S3アップロード
- WebP変換
- ALTテキスト生成(AI Gateway利用)
AI Gateway(Rust)
- 記事差分サマリ生成
- タイトル自動生成
- embed生成
Observability Stack
- Prometheusでメトリクス
- Lokiでログ集約
- Grafanaで可視化
サービス分割の理由
後ろにそれっぽいことがかいてありますが、ぶっちゃけ自分がWeb3層アーキテクチャーのことを親のように好きであり、プログラミング言語というものが好きなのでプログラミング言語を複数使ったさーびすってやつをやりたかっただけです。
1. 役割の境界を明確にするため
- 認証はAuth Service
- 記事ロジックはCore
- 外部投稿はPublisher
- 画像処理はUpload
責務を分けることで影響範囲を限定し、保守性を高める。
2. 技術の得意分野を活かすため
- Rails:外部連携・非同期ジョブが強い
- Rust:高速で安全な処理
- Go:認証とセキュリティ領域の実績
- C#:複雑な業務ロジックを扱いやすい
- TypeScript: ブラウザ上で動く処理が得意!
あと複数言語のコードを短期間に書くことで「俺はOO言語が好きだ!!」と言えるようになりたいです。
具体的には「こんにちは!PHPの布教に来ました!」とRuby・Goがメインの企業で言えるくらい愛を積み重ねていきたいですね。言語への愛をしっかり伝えていく姿、かっこいい。
3. Kubernetesのサービスメッシュ完全に理解したい
今回のアドカレからは99%漏れますが、サービスメッシュとかIstioとかってかっこよくないですか?会社でもEKSを扱っているのですがプライベートでも自宅鯖にk3s+istioみたいな構成で作ってるのでinternalな通信をするときのサービスメッシュの挙動とか実験するのに都合のいいアプリが欲しかったという需要がありました。
4. オブザーバビリティ何もわからんと言い続けてる自分が恥ずかしくなった
マジでなんもわからんので自分が自由にできる環境で「なるほどね???」といって触れるようになりたい。メトリクス仕込む側の気持ちになって「こういう苦労がありました」って自分の感性で言えるようになりたいと思ったわけです。
設計の原則
- 1サービス1責務
- 観測可能性を前提とする
- 再デプロイしやすい小さなコンポーネント
- 適材適所の技術選定
まとめ
本CMSは、巨大なモノリスではなく、
それぞれが最適化された小さなサービスを組み合わせた構造で設計しています。
- 障害の影響を局所化できる
- 新機能追加が容易
- 技術的負債が分散する
- 将来的な再構築がしやすい
明日の予告
明日は、「Day5: First Linter Fast CI — すべての基盤は “安定CI” から始まる」 です。
CIの話と本実装の準備パートが続きますがお付き合いください。