フィットネスアプリ バックエンドのスケーリング:Node.jsマイクロサービス事例
成長するフィットネスアプリのバックエンドをNode.jsモノリスから、DockerとKubernetesによるスケーラブルなマイクロサービスアーキテクチャへ移行する詳細な事例研究
このページの内容
FitTrackのバックエンドをモノリスからマイクロサービスへ移行したケーススタディについて、この文書から学ぶべきことを見ていきます。
競争の激しいフィットネス技術の世界において、アプリケーションのパフォーマンスとスケーラビリティは極めて重要です。動作の遅いアプリ線は、熱心なユーザーと離脱した订阅者の分かれ目となります。このケーススタディでは、架空ですが代表的なフィットネスアプリケーションである「FitTrack」が、バックエンドをモノリスアプリケーションからマイクロサービスの分散システムに移行した旅路を詳しく説明します。この重要なアーキテクチャ変更の動機、モノリスの分解プロセス、そしてそれを可能にした技術—Node.js、Docker、Kubernetes—について探索します。
この記事は、急速な成長を遂げているアプリケーションの課題に直面している開発者とエンジニアリングリーダーを対象としています。あなたのチームが遅い開発サイクル、デプロイのボトルネック、特定の機能のスケーリングの難しさで苦労している場合、この実際の物語は、成功する移行のための実践的なロードマップを提供するでしょう。
前提条件:
- Node.jsとRESTful APIの確かな理解。
- Dockerとコンテナ化の基本概念への熟悉。
- マイクロサービスアーキテクチャの高レベルな理解。
問題の理解
FitTrackは классическаяモノリスアーキテクチャで запустился。单个のNode.jsアプリケーションがすべてを處理:ユーザー認証、ワークアウト記録、ソーシャル交流、データレポート。このアプローチは、初期 запускаには最適で、迅速な開発と容易なデプロイを可能にしました。しかし、ユーザー層が指数関数的に成長するにつれて、モノリスは 그破绽を見せ始めました。
成長するモノリスの痛苦:
- スケーリングの非効率性: ソーシャル投稿を作成するユーザーの急増は、ワークアウト追跡とユーザープロファイルセクションが通常の負荷であっても、アプリケーション全体をスケールする必要があることを意味しました。これにより、不要なインフラコストが発生しました。
- 開発ボトルネック: 同じコードベースで作業する開発者チームの成長により、マージconflict、複雑な依存関係、そしてアプリケーション全体を壊す可能性がある変更を加えることへの恐怖が生じました。
- デプロイリスク: ソーシャルフィード機能 небольшаяバグが приложение全体を停止させ、ユーザーのワークアウト記録(重要な機能)を妨げる可能性がありました。デプロイは緊張感满满的でオールオアナッシングのイベントとなりました。
- テクノロジースタックの硬直性: モノリスアーキテクチャは、特定の機能でそれを有利に活用できたかもしれない新しい技術や言語の採用を困難にしました。
FitTrackチームは、成長をサポートし、より迅速にイノベーションを起こすために、より柔軟でスケーラブルで堅牢なアーキテクチャが必要であることを認識しました。マイクロサービスへの移行は不再是「かどうか」の問題ではなく、「いつ」と「どのように」の問題でした。
前提条件
移行に着手する前に、チームは必要なツールとローカル開発環境を確立しました:
- Node.js(v18以降): マイクロサービスのコアランタイム。
- Docker Desktop: ローカルでコンテナ化されたサービスをビルドおよび実行するため。
- Minikube: 开发和テスト用のローカルKubernetesクラスターをシミュレートするため。
- kubectl: Kubernetesクラスターとやり取りするためのコマンドラインツール。
- 各新しいマイクロサービス用のGitリポジトリ: コードを 독립管理するため。
ステップ1:モノリスの分解—ストラングラーフィグパターン
リスクが高く時間のかかる「ビッグバン」書き直しではなく、チームはストラングラーフィグパターンを選択しました。このアプローチは、既存のモノリスの周りに新しいマイクロサービスを徐々に構築し、その機能が停止されるまでゆっくりと「締め殺す」ことを中心にしています。
何をしているか
最初のステップは、モノリス内の明確なビジネス機能を識別し、ロジックサービスに分解することでした。ドメイン駆動設計(DDD)に導かれたこのプロセスは、以下の初期サービス分解をもたらしました:
- ユーザーサービス: ユーザープロファイル、認証、設定を担当。
- ワークアウトサービス: ワークアウトデータの作成、検索、更新、削除(CRUD)を処理。
- ソーシャルサービス: 投稿、いいね、コメントを含むソーシャルフィードを管理。
各サービスは、缓やかな結合を確保するために独自の独立したデータベースを持つことになります。
実装
チームはほとんどユーザーサービスから 开始しました。彼らは専用のPostgreSQLデータベースを持つ新しいNode.jsプロジェクトを作成しました。
// Express.jsを使用した初期ユーザーサービスの簡略図
// users-service/index.js
const express = require('express');
const app = express();
const port = 3001;
app.use(express.json());
// ダミーユーザーデータ
const users = [
{ id: 1, name: 'Alex', email: '[email protected]' },
{ id: 2, name: 'Maria', email: '[email protected]' },
];
app.get('/users/:id', (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) {
return res.status(404).send('User not found');
}
res.json(user);
});
app.listen(port, () => {
console.log(`Users service listening on port ${port}`);
});
動作原理
すべてのクライアントリクエストの單一エントリポイントとしてAPIゲートウェイが導入されました。最初は、ゲートウェイはほとんどのトラフィックをモノリスにルーティングしていました。しかし、/api/users/:idへのリクエストについては、それらを新しいユーザーサービスにdirectedしていました。この段階的なshiftは、エンドユーザーに対して透過的でした。
ステップ2:Dockerによるサービスのコンテナ化
最初のマイクロサービスが定義されたので、次のステップはDockerを使用してそれをコンテナ化することでした。これにより、ローカル開発から本番環境まで、各サービスの一貫性と再現可能な環境が確保されます。
何をしているか
各マイクロサービスに対してDockerfileが作成されました。このファイルには、ベースNode.jsイメージ、依存関係のインストール、アプリケーションを実行するコマンドなど、Dockerイメージをビルドするための命令が含まれています。
実装
# users-service/Dockerfile
# 軽量な公式Node.jsイメージを使用
FROM node:18-alpine
# コンテナ内の作業ディレクトリを設定
WORKDIR /usr/src/app
# package.jsonとpackage-lock.jsonをコピー
COPY package*.json ./
# 本番依存関係をインストール
RUN npm install --only=production
# 残りのアプリケーションコードをコピー
COPY . .
# アプリが実行されるポートを公開
EXPOSE 3001
# アプリケーションを実行するコマンド
CMD [ "node", "index.js" ]
動作原理
このDockerfileを使用すると、開発者は2つのシンプルなコマンドでコンテナ内でユーザーサービスをビルドおよび実行できます:
# Dockerイメージをビルド
docker build -t fittrack-users-service .
# コンテナを実行し、ポート3001をホストにマッピング
docker run -p 3001:3001 fittrack-users-service
このプロセスは、ワークアウトサービスとソーシャルサービスのために複製され、それぞれ独自のDockerfileを持ち、異なるポートで実行されました。
ステップ3:Kubernetesによるオーケストレーション
ローカルマシンで複数のDockerコンテナを実行するのは一方面ですが、スケーリング、フォールトトレランス、ゼロダウンタイムデプロイの 要求を伴う本番環境でそれらを管理するのは別の問題です。ここがKubernetesの出番です。
何をしているか
チームはKubernetesを使用して、コンテナ化されたマイクロサービスのデプロイ、スケーリング、管理を自動化しました。彼らは各サービスの望ましい状態を定義するために、Kubernetesマニフェストファイル(YAML形式)を作成しました。
実装
ユーザーサービスの簡略化されたdeployment.yamlは次のとおりです:
# users-service-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: users-service-deployment
spec:
replicas: 2 # 高可用性のために2つのインスタンスから開始
selector:
matchLabels:
app: users-service
template:
metadata:
labels:
app: users-service
spec:
containers:
- name: users-service
image: fittrack-users-service:latest # 使用するDockerイメージ
ports:
- containerPort: 3001
クラスター内でデプロイをexposeするために、service.yamlが作成されました:
# users-service-service.yaml
apiVersion: v1
kind: Service
metadata:
name: users-service
spec:
selector:
app: users-service
ports:
- protocol: TCP
port: 80
targetPort: 3001
動作原理
これらのYAMLファイルは、kubectl apply -f <filename>を使用してKubernetesクラスターに適用されます。Kubernetesは、users-serviceコンテナの2つのインスタンス(レプリカ)が常に実行されていることを保証するために 作動します。KubernetesのServiceは、デプロイのための安定したIPアドレスとDNS名を提供し、他のサービスが個々のコンテナIPを知る必要なしにそれと通信できるようにします。
すべてをまとめる:サービス間通信
マイクロサービスアーキテクチャにおける主要な課題の一つは、服務間の通信の管理です。例えば、ソーシャルサービスは、投稿を行ったユーザーの名前とプロフィール写真をどのように取得しますか?
チームコミュニケーションのためにハイブリッドアプローチを決定しました:
-
同期通信(REST API): 直接的リアルタイムデータリクエストの場合、サービスはRESTful HTTP呼び出し 통해通信します。例えば、ソーシャルサービスはユーザーの詳細を取得するためにユーザーサービス(
http://users-service/users/:id)にGETリクエストを行います。Kubernetesサービス発見メカニズムはこれをシームレスにします。 -
非同期通信(メッセージブローカー): 即座のresponseを必要としないイベントのために、チームはメッセージブローカー(RabbitMQ)を実装しました。ユーザーが新しいワークアウトを作成すると、ワークアウトサービスは
workout_createdイベントをpublishします。ソーシャルサービス(「新しいワークアウト」投稿を生成するため)や将来の成果サービスなどの他のサービスは、このイベントをsubscribe相应できます。これにより、サービスが分離され、耐障害性が向上します。
課題の克服:データ、監視、デプロイ
移行は困難なしではありませんでした:
-
データ整合性: 別々のデータベースにより、サービス間でのデータ整合性の維持が課題となりました。チームmultipleサービスにまたがるcomplexなトランザクションのためにサーガパターンを使用しました。このパターンはトランザクションを一連のローカルトランザクションに分解し、ステップが失敗した場合に変更をロールバックするためのcompensationトランザクションを伴います。
-
監視とログ記録: リクエストが複数のサービス間hoppingするため、エラーのsourceをpinpointingすることが困難になりました。ELK Stack(Elasticsearch、Logstash、Kibana)とPrometheus with Grafanaを使用した集中型ログ記録と監視solutionが実装されました。これにより、システム全体の健康状態とパフォーマンスの統合的なビューが提供されました。
-
CI/CDパイプライン: チームはGitHub Actionsを使用して、各マイクロサービスに対して独立したCI/CDパイプラインを設定しました。サービスのリポジトリのメインブランチへのpushは自動的にテストを実行し、新しいDockerイメージをビルドし、コンテナレジストリにpushし、ゼロダウンタイムでKubernetesクラスターにアップデートをデプロイしました。
結論
FitTrackのモノリスからマイクロサービスアーキテクチャへの移行は重要な事業でしたが、利点は変革的でした:
- スケーラビリティの向上: チームは需要に基づいて個々のサービスをスケールできるようになりました。
- 開発速度の向上: より小さくfocusedなチームは、サービスを独立して開発、テスト、デプロイできました。
- 耐障害性の向上: 1つのサービスの問題は приложение全体を停止させなくなりました。
- 技術的柔軟性: チームは各jobに最適なツールを自由に選択できるようになりました。
このケーススタディは、慎重な計画、適切なツール、そして段階的なアプローチにより、モノリスからマイクロサービスへの成功した移行は達成可能であり、成長しているアプリケーションの巨大な可能性を解き放つことができることをdemonstrates。
リソース
- 公式ドキュメント:
- 参考文献:
クイックリファレンス
| 側面 | 重要な情報 |
|---|---|
| トピック | 開発 |
| 関連性 | 患者教育と認識 |
| 対応 | 医療、提供者と相談してください |
| 頻度 | ケアチームの推奨に応じて |
| エビデンス | 現在の臨床ガイドラインに基づく |
よくある質問
Q: これが自分に該当するどうかはどうやってわかりますか? A: 個人的な病史と家族歷について医療提供者と相談し、個人のリスク要因と適切な次のステップを評価してください。
Q: 医師に何を聞くべきですか? A: 良い質問には、「結果はどういう意味ですか?」「私のオプションは何ですか?」「どんな生活習慣の改善が役立ちますか?」「いつフォローアップすべきですか?」があります。
Q: 役立つ生活習慣の改善はありますか? A: ほとんどの健康状態は、基本的な対策からbenefitsします:バランスの取れた栄養、定期的な運動(週150分以上)、質のよい睡眠(7〜9時間)、ストレス管理、タバコの回避。
医療免責事項
この記事は教育目的のみを目的としており、医療adviceを構成しません。あなたの健康、治療、またはケアに関する決定する前に、常に資格のある医療提供者と相談してください。個人の状況是不一样的、一人に適切なことがもう一人の人にappropriateではないかもしれません。
医療緊急状態が発生した場合は、直ちに119番(または地元の緊急番号)に電話してください。