- Authors

- Name
- Youngju Kim
- @fjvbn20031
目次
1. API設計原則
1.1 Richardson成熟度モデル
Leonard Richardsonが提唱したREST成熟度モデルは、APIのRESTful度合いを4段階で分類する。
| レベル | 名前 | 説明 |
|---|---|---|
| Level 0 | The Swamp of POX | 単一URI、単一HTTPメソッド(通常POST) |
| Level 1 | Resources | 個別リソースURI使用、依然として単一メソッド |
| Level 2 | HTTP Verbs | HTTPメソッドを適切に活用(GET、POST、PUT、DELETE) |
| Level 3 | Hypermedia Controls | HATEOAS - レスポンスに次のアクションリンクを含む |
多くの実務APIはLevel 2を目標としており、Level 3(HATEOAS)は実装の複雑さに対して実質的なメリットが少ないため、選択的に適用される。
1.2 リソースネーミング規約
良いAPI設計の核心は、一貫したリソースネーミングである。
# 良い例
GET /api/v1/users
GET /api/v1/users/123
GET /api/v1/users/123/orders
POST /api/v1/users
PUT /api/v1/users/123
DELETE /api/v1/users/123
# 悪い例
GET /api/v1/getUsers
POST /api/v1/createUser
GET /api/v1/user_list
核心原則:
- 名詞を使用: リソースは名詞で表現する(users、orders、products)
- 複数形: コレクションは複数形を使用する(/users、/orders)
- 小文字 + ハイフン: kebab-caseを使用する(/order-items)
- 階層関係: ネストしたリソースで表現する(/users/123/orders)
- フィルタリングはクエリパラメータ: /users?status=active&role=admin
1.3 HTTPメソッドとステータスコード
GET - 取得(安全、冪等)
POST - 作成(非安全、非冪等)
PUT - 全体更新(非安全、冪等)
PATCH - 部分更新(非安全、非冪等)
DELETE - 削除(非安全、冪等)
OPTIONS - CORSプリフライト
HEAD - ヘッダーのみ取得
主要ステータスコードガイド:
| コード | 意味 | 使用タイミング |
|---|---|---|
| 200 | OK | 成功したGET、PUT、PATCH |
| 201 | Created | 成功したPOST(Locationヘッダー含む) |
| 204 | No Content | 成功したDELETE |
| 400 | Bad Request | 不正なリクエスト形式 |
| 401 | Unauthorized | 認証失敗 |
| 403 | Forbidden | 権限なし |
| 404 | Not Found | リソースなし |
| 409 | Conflict | リソース競合 |
| 422 | Unprocessable Entity | バリデーション失敗 |
| 429 | Too Many Requests | Rate Limit超過 |
| 500 | Internal Server Error | サーバーエラー |
1.4 リクエスト/レスポンス設計
一貫したレスポンス形式は、クライアント開発体験を大幅に向上させる。
{
"data": {
"id": "user_123",
"type": "user",
"attributes": {
"name": "田中太郎",
"email": "tanaka@example.com",
"created_at": "2026-04-12T10:00:00Z"
}
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-04-12T10:00:00Z"
}
}
ページネーションレスポンス:
{
"data": [],
"pagination": {
"page": 1,
"per_page": 20,
"total": 150,
"total_pages": 8,
"next_cursor": "eyJpZCI6MTAwfQ=="
}
}
エラーレスポンス:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "リクエストデータが無効です",
"details": [
{
"field": "email",
"message": "正しいメール形式ではありません"
}
]
}
}
2. REST vs GraphQL vs gRPC 比較
2.1 比較表
| 特性 | REST | GraphQL | gRPC |
|---|---|---|---|
| プロトコル | HTTP/1.1 | HTTP/1.1 | HTTP/2 |
| データ形式 | JSON/XML | JSON | Protocol Buffers |
| スキーマ | OpenAPI(任意) | SDL(必須) | .proto(必須) |
| 型安全性 | 弱い | 強い | 非常に強い |
| オーバー/アンダーフェッチ | あり | 解決 | 解決 |
| リアルタイム | WebSocket | Subscription | 双方向ストリーミング |
| ブラウザサポート | ネイティブ | ネイティブ | grpc-web必要 |
| パフォーマンス | 普通 | 普通 | 高い |
| 学習コスト | 低い | 中程度 | 高い |
2.2 各技術の適切な使用ケース
RESTが適している場合:
- 公開API(Open API)
- 単純なCRUD操作
- キャッシングが重要な場合(HTTPキャッシング活用)
- ブラウザから直接呼び出す場合
GraphQLが適している場合:
- モバイルアプリ(帯域幅最適化)
- 複雑なデータ関係がある場合
- 異なるクライアントが異なるデータを要求する場合
- 高速なフロントエンド開発サイクル
gRPCが適している場合:
- マイクロサービス間の内部通信
- 高いパフォーマンスが必要な場合
- 双方向ストリーミングが必要な場合
- 多言語環境
2.3 GraphQL例
# スキーマ定義
type User {
id: ID!
name: String!
email: String!
orders: [Order!]!
}
type Order {
id: ID!
total: Float!
status: OrderStatus!
items: [OrderItem!]!
}
type Query {
user(id: ID!): User
users(page: Int, limit: Int): [User!]!
}
type Mutation {
createUser(input: CreateUserInput!): User!
updateUser(id: ID!, input: UpdateUserInput!): User!
}
# クライアントクエリ - 必要なフィールドのみリクエスト
query GetUserWithOrders {
user(id: "123") {
name
email
orders {
id
total
status
}
}
}
2.4 gRPC例
syntax = "proto3";
package ecommerce;
service UserService {
rpc GetUser (GetUserRequest) returns (UserResponse);
rpc ListUsers (ListUsersRequest) returns (stream UserResponse);
rpc CreateUser (CreateUserRequest) returns (UserResponse);
}
message GetUserRequest {
string user_id = 1;
}
message UserResponse {
string id = 1;
string name = 2;
string email = 3;
int64 created_at = 4;
}
message ListUsersRequest {
int32 page = 1;
int32 limit = 2;
}
message CreateUserRequest {
string name = 1;
string email = 2;
}
3. APIバージョニング
3.1 バージョニング戦略比較
| 戦略 | 例 | 利点 | 欠点 |
|---|---|---|---|
| URIバージョニング | /api/v1/users | 直感的、キャッシュ容易 | URI汚染 |
| ヘッダーバージョニング | Accept: application/vnd.api+json;version=1 | URIクリーン | テスト困難 |
| クエリバージョニング | /api/users?version=1 | 実装簡単 | キャッシュ複雑 |
| Content Negotiation | Accept: application/vnd.company.v1+json | 標準準拠 | 複雑 |
URIバージョニングが最も広く使用されており、実用性と明確さの面で推奨される。
3.2 後方互換性維持の原則
後方互換可能な変更(非破壊的):
- 新しいエンドポイントの追加
- レスポンスへの新しいフィールドの追加
- オプションのリクエストパラメータの追加
- 新しいenum値の追加(クライアントがunknown処理する場合)
後方互換不可能な変更(破壊的):
- 既存フィールドの削除またはリネーム
- フィールド型の変更
- 必須パラメータの追加
- レスポンス構造の変更
- URLパスの変更
3.3 API廃止戦略
Phase 1: Sunsetヘッダー追加
Sunset: Sat, 01 Jan 2027 00:00:00 GMT
Deprecation: true
Link: <https://api.example.com/v2/docs>; rel="successor-version"
Phase 2: レスポンスに警告を含める(6ヶ月間)
Phase 3: Rate limitを段階的に縮小(3ヶ月間)
Phase 4: 410 Goneレスポンスを返す
4. 認証/認可 (Authentication / Authorization)
4.1 認証方式比較
| 方式 | セキュリティレベル | 使用ケース | 複雑度 |
|---|---|---|---|
| API Key | 低い | 内部/パートナーAPI | 低い |
| OAuth 2.0 | 高い | ユーザー認証委譲 | 高い |
| JWT | 中程度 | ステートレス認証 | 中程度 |
| mTLS | 非常に高い | サービス間通信 | 高い |
4.2 OAuth 2.0フロー
Authorization Code Flow(サーバーサイドアプリ推奨):
1. クライアント --> 認可サーバー: 認可コードリクエスト
GET /authorize?response_type=code
&client_id=CLIENT_ID
&redirect_uri=CALLBACK_URL
&scope=read:user
&state=RANDOM_STATE
2. ユーザー --> 認可サーバー: ログインおよび権限同意
3. 認可サーバー --> クライアント: 認可コード返却
302 Redirect: CALLBACK_URL?code=AUTH_CODE&state=RANDOM_STATE
4. クライアント --> 認可サーバー: トークン交換
POST /token
grant_type=authorization_code
&code=AUTH_CODE
&client_id=CLIENT_ID
&client_secret=CLIENT_SECRET
5. 認可サーバー --> クライアント: アクセストークン + リフレッシュトークン
4.3 JWT構造とセキュリティ
{
"header": {
"alg": "RS256",
"typ": "JWT",
"kid": "key-id-001"
},
"payload": {
"sub": "user_123",
"iss": "auth.example.com",
"aud": "api.example.com",
"exp": 1744540800,
"iat": 1744537200,
"scope": "read:users write:orders",
"roles": ["admin"]
}
}
JWTセキュリティチェックリスト:
- RS256(非対称)アルゴリズムの使用を推奨(HS256より安全)
- 短い有効期限の設定(15分以下)
- リフレッシュトークンはサーバーサイドに保存
- iss、aud、expクレームを必ず検証
- noneアルゴリズムを拒否
- kid(Key ID)検証でキー混同攻撃を防止
4.4 mTLS(相互TLS)
サービス間通信セキュリティ:
1. 各サービスに固有のX.509証明書を発行
2. 通信時に双方向の証明書検証
3. 証明書の自動更新(cert-managerなど)
メリット:
- サービスIDを暗号学的に証明
- ネットワークレベルでの暗号化
- Zero Trustアーキテクチャの基盤
デメリット:
- 証明書管理の複雑さ
- 証明書期限切れ時のサービス停止リスク
- デバッグの困難さ
5. Rate Limiting
5.1 アルゴリズム比較
Token Bucket:
原理: 一定速度でトークンが追加され、リクエスト時にトークンを消費
メリット: バーストトラフィックを許容しつつ平均速度を維持
デメリット: メモリ使用
例:
- バケットサイズ: 100トークン
- 補充速度: 10トークン/秒
- リクエストごとに1トークン消費
- バースト: 最大100リクエスト同時可能
Sliding Window:
原理: 時間ウィンドウ内のリクエスト数をカウント
メリット: 正確な制限、ウィンドウ境界問題を解決
デメリット: 前のウィンドウカウンターの保存が必要
例:
現在時刻: 12:01:30
前のウィンドウ (12:00-12:01): 80リクエスト
現在のウィンドウ (12:01-12:02): 20リクエスト
加重合計: 80 * 0.5 + 20 = 60(上限100以内)
5.2 Rate Limitレスポンスヘッダー
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1744540860
Retry-After: 60
5.3 API Gatewayを用いたRate Limiting
# Kong Gateway設定例
plugins:
- name: rate-limiting
config:
minute: 100
hour: 1000
policy: redis
redis_host: redis-cluster
redis_port: 6379
fault_tolerant: true
hide_client_headers: false
6. マイクロサービスパターン
6.1 サービス分割基準 - DDD Bounded Context
Eコマースドメイン分析:
[注文コンテキスト] [商品コンテキスト]
- Order - Product
- OrderItem - Category
- OrderStatus - Inventory
- Payment - Price
[ユーザーコンテキスト] [配送コンテキスト]
- User - Shipment
- Address - Tracking
- Authentication - Carrier
- Profile - Delivery
[通知コンテキスト] [検索コンテキスト]
- Notification - SearchIndex
- Template - Filter
- Channel - Ranking
分割原則:
- ビジネスケイパビリティ基準で分割
- データオーナーシップ: 各サービスが自身のデータベースを所有
- チーム自律性: ツーピザチームルール(6-8人)
- デプロイ独立性: 他サービスの変更なしにデプロイ可能
- 疎結合、高凝集
6.2 サービス通信 - 同期 vs 非同期
同期通信(Request-Response):
[API Gateway] --> [Order Service] --> [Payment Service]
--> [Inventory Service]
メリット: 即時レスポンス、実装が簡単
デメリット: 強い結合、連鎖障害、レイテンシ累積
非同期通信(Event-Driven):
[Order Service] --> [Message Broker] --> [Payment Service]
--> [Inventory Service]
--> [Notification Service]
メリット: 疎結合、高い復元力、スケーラビリティ
デメリット: 最終的な整合性、デバッグの困難さ
Kafka vs RabbitMQ比較:
| 特性 | Apache Kafka | RabbitMQ |
|---|---|---|
| モデル | Pub/Sub + Log | Queue + Exchange |
| 順序保証 | パーティション内で保証 | キュー内で保証 |
| スループット | 非常に高い(数百万/秒) | 高い(数万/秒) |
| メッセージ保持 | 設定期間中保持 | 消費後削除 |
| 再処理 | オフセットリセットで可能 | 不可能(DLQ使用) |
| 使用ケース | イベントストリーミング、ログ | タスクキュー、RPC |
6.3 API Gatewayパターン
役割:
- リクエストルーティング
- 認証/認可
- Rate Limiting
- ロードバランシング
- リクエスト/レスポンス変換
- サーキットブレイカー
- モニタリング/ロギング
主要ソリューション:
- Kong: オープンソース、プラグインエコシステム
- Envoy: 高性能、L7プロキシ
- AWS API Gateway: マネージド、サーバーレス
- NGINX: 軽量、高パフォーマンス
- Traefik: 自動サービスディスカバリ
# Envoyルーティング設定例
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
route_config:
virtual_hosts:
- name: backend
domains: ["*"]
routes:
- match:
prefix: "/api/v1/users"
route:
cluster: user_service
- match:
prefix: "/api/v1/orders"
route:
cluster: order_service
6.4 サービスディスカバリ
クライアントサイドディスカバリ:
1. サービスA --> サービスレジストリ: サービスBのアドレスを検索
2. サービスA --> サービスB: 直接呼び出し
ツール: Eureka、Consul
サーバーサイドディスカバリ:
1. サービスA --> ロードバランサー: リクエスト
2. ロードバランサー --> サービスレジストリ: アドレス検索
3. ロードバランサー --> サービスB: 転送
ツール: K8s Service + DNS、AWS ALB
Kubernetes DNSベース:
サービス内部DNS: service-name.namespace.svc.cluster.local
例: order-service.production.svc.cluster.local
6.5 Circuit Breakerパターン
状態遷移:
[Closed] --失敗閾値超過--> [Open]
[Open] --タイムアウト経過--> [Half-Open]
[Half-Open] --成功--> [Closed]
[Half-Open] --失敗--> [Open]
// Resilience4j設定例
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50) // 50%失敗でOpen
.waitDurationInOpenState(
Duration.ofSeconds(30)) // 30秒後にHalf-Open
.slidingWindowSize(10) // 直近10リクエスト基準
.minimumNumberOfCalls(5) // 最低5回呼び出し後に判断
.permittedNumberOfCallsInHalfOpenState(3)
.build();
CircuitBreaker circuitBreaker = CircuitBreaker.of(
"paymentService", config);
Supplier<PaymentResponse> decoratedSupplier =
CircuitBreaker.decorateSupplier(
circuitBreaker,
() -> paymentService.processPayment(request)
);
フォールバック戦略:
- キャッシュされたレスポンスを返す: 前回の成功レスポンスを使用
- デフォルト値を返す: 事前定義されたデフォルトレスポンス
- 代替サービスを呼び出す: バックアップサービスを使用
- グレースフルデグラデーション: 機能縮小レスポンス
7. サービスメッシュ
7.1 サービスメッシュとは?
サービスメッシュアーキテクチャ:
[Service A] <--> [Sidecar Proxy] <--> [Sidecar Proxy] <--> [Service B]
| |
v v
[Control Plane (Istio/Linkerd)]
|
[設定、ポリシー、証明書管理]
サイドカープロキシの役割:
- トラフィックルーティングとロードバランシング
- mTLS暗号化
- サーキットブレイカー
- リトライとタイムアウト
- メトリクス収集
- 分散トレーシング
7.2 Istio vs Linkerd
| 特性 | Istio | Linkerd |
|---|---|---|
| データプレーン | Envoy | linkerd2-proxy (Rust) |
| リソース使用量 | 高い | 低い |
| 機能 | 非常に豊富 | コア機能に集中 |
| 学習コスト | 急勾配 | なだらか |
| コミュニティ | Google主導 | CNCF Graduated |
| マルチクラスタ | サポート | サポート |
7.3 Istioトラフィック管理
# カナリアデプロイメント - トラフィック分割
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: order-service
spec:
hosts:
- order-service
http:
- route:
- destination:
host: order-service
subset: v1
weight: 90
- destination:
host: order-service
subset: v2
weight: 10
retries:
attempts: 3
perTryTimeout: 2s
retryOn: 5xx,reset,connect-failure
timeout: 10s
# サーキットブレイカー設定
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: order-service
spec:
host: order-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
h2UpgradePolicy: DEFAULT
http1MaxPendingRequests: 100
http2MaxRequests: 1000
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
8. イベント駆動アーキテクチャ
8.1 Event Sourcing
従来の方式: 現在の状態のみ保存
ordersテーブル: id=1, status=SHIPPED, total=50000
Event Sourcing: すべての状態変更をイベントとして保存
eventsテーブル:
1. OrderCreated (total=50000)
2. PaymentReceived (amount=50000)
3. OrderConfirmed ()
4. ItemShipped (tracking=KR123456)
メリット:
- 完全な監査ログ
- タイムトラベル(特定時点の状態を再現)
- イベントリプレイで新しいビューを生成
- デバッグが容易
デメリット:
- イベントスキーマの進化管理
- イベントストアのサイズ増大
- 最終的な整合性(Eventual Consistency)
8.2 CQRS (Command Query Responsibility Segregation)
CQRSアーキテクチャ:
[Command] --> [Write Model] --> [Event Store]
|
[Event Bus]
|
[Read Modelプロジェクション]
|
[Query] <-- [Read DB]
Command(書き込み):
- ドメインロジック実行
- イベント発行
- 正規化されたデータベース
Query(読み取り):
- 非正規化された読み取り専用ビュー
- 高速クエリに最適化
- 多様なストレージ使用可能(ES、Redisなど)
8.3 Sagaパターン - 分散トランザクション
マイクロサービス環境では、2PC(Two-Phase Commit)にはパフォーマンスと可用性の問題がある。Sagaパターンは、ローカルトランザクションのシーケンスで分散トランザクションを管理する。
Choreography(振付)方式:
注文作成Saga:
[Order Service] [Payment Service] [Inventory Service]
| | |
OrderCreated --------> | |
| PaymentProcessed --------> |
| | InventoryReserved
| | |
| <--- (成功時) ---> |
OrderConfirmed | |
補償トランザクション(失敗時):
InventoryReserveFailed --> PaymentRefunded --> OrderCancelled
Orchestration(オーケストレーション)方式:
[Order Saga Orchestrator]
|
|--> 1. Order Service: 注文作成
|--> 2. Payment Service: 決済処理
|--> 3. Inventory Service: 在庫予約
|--> 4. Shipping Service: 配送作成
|
(失敗時は逆順で補償)
|--> 3c. Inventory: 在庫解放
|--> 2c. Payment: 返金処理
|--> 1c. Order: 注文取消
9. 分散トレーシング
9.1 Correlation IDパターン
リクエストフロー:
[Client]
X-Request-ID: req-abc-123
|
[API Gateway]
X-Request-ID: req-abc-123
X-Correlation-ID: corr-xyz-789
|
[Order Service] ----------> [Payment Service]
trace_id: corr-xyz-789 trace_id: corr-xyz-789
span_id: span-001 span_id: span-002
parent_span_id: null parent_span_id: span-001
|
----------> [Inventory Service]
trace_id: corr-xyz-789
span_id: span-003
parent_span_id: span-001
9.2 OpenTelemetry導入
// OpenTelemetry SDK初期化
import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({
url: 'http://otel-collector:4317',
}),
instrumentations: [
new HttpInstrumentation(),
new ExpressInstrumentation(),
],
});
sdk.start();
// 手動スパン作成
import { trace, SpanStatusCode } from '@opentelemetry/api';
const tracer = trace.getTracer('order-service');
async function processOrder(orderId: string) {
const span = tracer.startSpan('processOrder', {
attributes: {
'order.id': orderId,
'service.name': 'order-service',
},
});
try {
span.addEvent('Validating order');
await validateOrder(orderId);
span.addEvent('Processing payment');
await processPayment(orderId);
span.setStatus({ code: SpanStatusCode.OK });
} catch (error) {
span.setStatus({
code: SpanStatusCode.ERROR,
message: String(error),
});
throw error;
} finally {
span.end();
}
}
9.3 オブザーバビリティの3本柱
1. ログ(Logs):
- 構造化ログ(JSON)
- ログレベル(DEBUG、INFO、WARN、ERROR)
- Correlation IDを含める
- ELK Stack / Loki
2. メトリクス(Metrics):
- REDメトリクス: Rate、Errors、Duration
- USEメトリクス: Utilization、Saturation、Errors
- Prometheus + Grafana
3. トレース(Traces):
- 分散リクエスト追跡
- スパン(Span)ベースの可視化
- Jaeger / Zipkin / Tempo
10. 実践: Eコマースシステム MSA設計
10.1 全体アーキテクチャ
[CDN / CloudFront]
|
[API Gateway (Kong)]
/ | | \
/ | | \
[User Service] [Product] [Order] [Payment]
| Service Service Service
| | | |
[User DB] [Product DB] [Order DB] [Payment DB]
(PostgreSQL) (PostgreSQL) (PostgreSQL) (PostgreSQL)
| |
[Search Service] [Notification]
| Service
[Elasticsearch] |
[Kafka]
|
[Email/SMS/Push]
10.2 サービスごとの技術スタック
User Service:
- 言語: Go
- DB: PostgreSQL
- キャッシュ: Redis(セッション)
- 通信: REST + gRPC
Product Service:
- 言語: Java (Spring Boot)
- DB: PostgreSQL
- キャッシュ: Redis(商品情報)
- 検索: Elasticsearch
- 通信: REST + gRPC
Order Service:
- 言語: Java (Spring Boot)
- DB: PostgreSQL
- メッセージング: Kafka(注文イベント)
- 通信: gRPC + Kafka
Payment Service:
- 言語: Go
- DB: PostgreSQL
- 外部: 決済ゲートウェイ連携
- 通信: gRPC
Notification Service:
- 言語: Node.js
- DB: MongoDB(テンプレート)
- メッセージング: Kafka Consumer
- 外部: SendGrid、Firebase
10.3 注文処理フロー
1. クライアント --> API Gateway: POST /api/v1/orders
2. API Gateway --> Order Service: 注文作成リクエスト
3. Order Service --> Product Service (gRPC): 在庫確認
4. Order Service --> Kafka: OrderCreatedイベント発行
5. Payment Service (Consumer): 決済処理
6. Payment Service --> Kafka: PaymentCompletedイベント
7. Order Service (Consumer): 注文ステータス更新
8. Notification Service (Consumer): 注文確認メール送信
9. Product Service (Consumer): 在庫差し引き
10.4 障害対応戦略
Circuit Breaker:
- Paymentサービス障害時は注文受付のみ進行
- 決済はKafkaキューに積載後に再処理
Retry + Exponential Backoff:
- 1回目リトライ: 100ms
- 2回目リトライ: 200ms
- 3回目リトライ: 400ms
- 最大リトライ: 5回
Bulkheadパターン:
- サービスごとにスレッドプールを隔離
- 1つのサービス障害が全体に波及しないように隔離
Dead Letter Queue:
- 処理失敗メッセージをDLQに移動
- 手動分析および再処理
- アラート設定で運用チームに通知
10.5 デプロイ戦略
# Kubernetes Deployment - カナリアデプロイメント
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service-canary
labels:
app: order-service
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: order-service
version: v2
template:
metadata:
labels:
app: order-service
version: v2
spec:
containers:
- name: order-service
image: order-service:2.0.0
ports:
- containerPort: 8080
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
まとめ
API設計とマイクロサービスアーキテクチャは、現代のソフトウェア開発における核心的な能力である。重要なポイントをまとめると以下の通りだ。
- API設計は契約である - 一貫したネーミング、適切なステータスコード、明確なエラーメッセージが開発生産性を決定する
- 技術選択はコンテキスト次第 - REST、GraphQL、gRPCそれぞれの強みが異なり、混用が一般的である
- セキュリティは最初から - 認証/認可、mTLS、Rate Limitingは後回しにせず設計段階から考慮すべきだ
- サービス分割は慎重に - DDD Bounded Contextに基づき、小さすぎず大きすぎないように分割する
- 障害は必ず起きる - Circuit Breaker、Retry、Bulkhead、Sagaパターンで復元力を確保する
- オブザーバビリティこそ運用力 - ログ、メトリクス、トレースの3要素を統合して問題を迅速に把握する
モノリスから始めて、実際の必要性に応じて段階的にマイクロサービスを導入するのが最も賢明なアプローチである。技術的な優雅さよりもビジネス価値の提供に集中しよう。