導入
マイクロサービスアーキテクチャは、システムを小さな独立したサービスに分割することで、スケーラビリティや柔軟性を向上させる手法です。特にJavaScriptは、Node.jsの普及によりマイクロサービスの実装において人気の選択肢となっています。本記事では、実際の業務で遭遇しやすい具体的なシチュエーションをもとに、マイクロサービスの設計と実装について深掘りします。
教科書レベルの解説(マイクロサービス)
重要な概念の整理
マイクロサービスは、各サービスが独自の機能を持ち、APIを介して通信する構造を採用しています。このアーキテクチャの利点は、各サービスを独立して開発・デプロイできる点です。しかし、サービス間の通信やデータの整合性を保つことが課題となります。特に、複数のマイクロサービスが連携する際に、トランザクション管理やエラーハンドリングが重要です。
コード例(JavaScript)
const express = require('express');
const axios = require('axios');
const app = express();
const PORT = 3000;
app.get('/user/:id', async (req, res) => {
try {
const userId = req.params.id;
const userResponse = await axios.get(`http://user-service/users/${userId}`);
const ordersResponse = await axios.get(`http://order-service/orders?userId=${userId}`);
res.json({
user: userResponse.data,
orders: ordersResponse.data
});
} catch (error) {
res.status(500).send('Internal Server Error');
}
});
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
コードの行ごとの解説
- const express = require(‘express’); – Expressフレームワークをインポートし、サーバーを構築する準備をします。
- const axios = require(‘axios’); – HTTPリクエストを簡単に行うためにaxiosをインポートします。
- const app = express(); – Expressアプリケーションのインスタンスを作成します。
- app.get(‘/user/:id’, async (req, res) => { – ユーザー情報を取得するためのエンドポイントを定義します。
- const userId = req.params.id; – リクエストパラメータからユーザーIDを取得します。
- const userResponse = await axios.get(…); – ユーザーサービスからユーザー情報を非同期で取得します。
- const ordersResponse = await axios.get(…); – 注文サービスからユーザーの注文情報を非同期で取得します。
- res.json({…}); – 取得したユーザー情報と注文情報をJSON形式でレスポンスします。
- catch (error) { res.status(500).send(‘Internal Server Error’); } – エラーが発生した場合、500エラーレスポンスを返します。
- app.listen(PORT, () => {…}); – サーバーを指定したポートで起動します。
解説編
このコード例では、ユーザー情報を取得するために、ユーザーサービスと注文サービスの2つのマイクロサービスにリクエストを行っています。このような構成では、サービス間の依存関係が生じ、1つのサービスがダウンすると他のサービスにも影響を及ぼす可能性があります。これを防ぐためには、サービスの冗長化やフォールトトレランスを考慮する必要があります。また、タイムアウトやリトライロジックを実装することで、エラー時のユーザーエクスペリエンスを向上させることができます。
まとめ
- マイクロサービスは独立したサービスの集合体であり、スケーラビリティを向上させる。
- サービス間の通信においては、エラーハンドリングやデータ整合性が重要な課題である。
- 冗長化やフォールトトレランスを考慮した設計が必要である。