Feature 40: 地理的分散ノード管理システム
Copyright: 2026 Moonlight Technologies Inc.
Author: Masahiro Aoki
実装日: 2026年2月20日
バージョン: 1.0.0
ステータス: ✅ 実装済み
概要
EvoSpikeNet の地理的分散ノード管理システム(Feature 40)は、世界中に分散したノードをリージョン単位で管理し、障害時の自動フェイルオーバーとリージョン間レイテンシー最適化を提供します。
現状: 基本機能とAPIは動作しているものの、 一部モジュールが「🟡 部分実装」扱いとなっています。 ユニット・統合・性能テストは完備されており、 ドキュメントリンクの整備と追加テストによる完全判定を進めています。
アーキテクチャ
┌─────────────────────────────────────────────────────────┐
│ GeoNodeManager │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ GeoRegion │ │ GeoNode │ │ LatencyMatrix │ │
│ │ (5 default)│ │ (per node) │ │ (N×N regions) │ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Background Health Poller (30s interval) │ │
│ │ → RegionStatus update → Failover trigger │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
デフォルト登録リージョン
GeoNodeManager は起動時に以下の5リージョンを自動登録します。
| リージョンID | 表示名 | 緯度 | 経度 | 優先度 |
|---|---|---|---|---|
ap-northeast-1 |
Asia Pacific (Tokyo) | 35.68 | 139.69 | 1 |
us-east-1 |
US East (N. Virginia) | 39.04 | -77.49 | 2 |
us-west-2 |
US West (Oregon) | 45.52 | -122.68 | 3 |
eu-west-1 |
Europe (Ireland) | 53.33 | -6.25 | 4 |
ap-southeast-1 |
Asia Pacific (Singapore) | 1.35 | 103.82 | 5 |
レイテンシー計算
リージョン間レイテンシーは Haversine 式による実際の地球上の距離から推定します。
\[d = 2r \cdot \arcsin\left(\sqrt{\sin^2\left(\frac{\phi_2 - \phi_1}{2}\right) + \cos\phi_1 \cos\phi_2 \sin^2\left(\frac{\lambda_2 - \lambda_1}{2}\right)}\right)\]
latency_ms = distance_km / 200.0 * 1000 + jitter_ms
東京 → バージニア: 約 145ms(地球一周の約 1/3)
東京 → シンガポール: 約 32ms
コアコンポーネント
GeoRegion
<!-- from evospikenet.geo_node_manager import GeoRegion, RegionStatus -->
region = GeoRegion(
region_id="ap-northeast-1",
display_name="Asia Pacific (Tokyo)",
provider="aws",
latitude=35.6762,
longitude=139.6503,
priority=1,
)
print(region.status) # RegionStatus.ONLINE
RegionStatus:
| 値 | 説明 |
|---|---|
online |
正常稼働中 |
offline |
オフライン |
degraded |
性能低下中 |
maintenance |
メンテナンス中 |
unknown |
状態不明 |
GeoNode
<!-- TODO: update or remove - import failmport GeoNode, NodeGeoStatus -->
node = GeoNode(
node_id="prod-gpu-node-01",
region_id="ap-northeast-1",
endpoint="10.0.1.100:8000",
node_type="gpu", # general / gpu / scheduler / storage
)
GeoNodeManager
<!-- モジュール 'evospikenet' が見つかりません。パッケージ内の移動/名前変更を確認してください -->
<!-_node_manager.add_region(region)
geo_node_manager.get_region("ap-northeast-1")
geo_node_manager.remove_region("ap-northeast-1")
regions = geo_node_manager.list_regions()
# ノード操作
geo_node_manager.register_node(node)
geo_node_manager.deregister_node("prod-gpu-node-01")
nodes = geo_node_manager.list_nodes(region_id="ap-northeast-1")
# アクティブリージョン
active = geo_node_manager.get_active_region()
geo_node_manager.set_active_region("us-east-1")
# フェイルオーバー
event = geo_node_manager.trigger_failover(
from_region="ap-northeast-1",
to_region="us-east-1",
reason="region_health_check_failed",
triggered_by="health_monitor",
)
# レイテンシー行列
matrix = geo_node_manager.get_latency_matrix()
# matrix["ap-northeast-1"]["us-east-1"] == 145.3
# レプリケーショングループ
source, targets, latencies = geo_node_manager.get_replication_group("ap-northeast-1")
REST API
GET /api/geo/status
レスポンス例:
{
"active_region": "ap-northeast-1",
"total_regions": 5,
"total_nodes": 12,
"online_regions": 5,
"regions": {
"ap-northeast-1": {
"status": "online",
"node_count": 4,
"priority": 1
}
}
}
GET /api/geo/regions
全リージョン一覧を返します。
POST /api/geo/regions
新しいリージョンを登録します。
リクエストボディ:
{
"region_id": "ap-northeast-3",
"display_name": "Asia Pacific (Osaka)",
"provider": "aws",
"location": { "lat": 34.69, "lon": 135.50 },
"priority": 6
}
GET /api/geo/regions/{region_id}
DELETE /api/geo/regions/{region_id}
GET /api/geo/nodes
クエリパラメータ: region_id, status
POST /api/geo/nodes
リクエストボディ:
{
"node_id": "prod-gpu-node-01",
"region_id": "ap-northeast-1",
"endpoint": "10.0.1.100:8000",
"node_type": "gpu"
}
DELETE /api/geo/nodes/{node_id}
POST /api/geo/failover
手動フェイルオーバーを実行します。
リクエストボディ:
{
"from_region": "ap-northeast-1",
"to_region": "us-east-1",
"reason": "region_unavailable",
"triggered_by": "operator"
}
レスポンス:
{
"status": "failover_executed",
"event": {
"event_id": "550e8400-...",
"from_region": "ap-northeast-1",
"to_region": "us-east-1",
"timestamp": "2026-02-20T10:30:00Z",
"reason": "region_unavailable",
"triggered_by": "operator",
"success": true
}
}
GET /api/geo/failover/history
クエリパラメータ: limit (デフォルト: 20)
GET /api/geo/latency-matrix
レスポンス例:
{
"matrix": {
"ap-northeast-1": {
"us-east-1": 145.3,
"us-west-2": 110.2,
"eu-west-1": 230.1,
"ap-southeast-1": 32.4
},
"us-east-1": {
"ap-northeast-1": 145.3,
...
}
}
}
GET /api/geo/active-region
PUT /api/geo/active-region
リクエストボディ:
{ "region_id": "us-east-1" }
GET /api/geo/replication-group/{region_id}
レスポンス例:
{
"source_region": "ap-northeast-1",
"replication_targets": ["ap-southeast-1", "us-west-2"],
"latencies_ms": {
"ap-southeast-1": 32.4,
"us-west-2": 110.2
}
}
フェイルオーバーフロー
1. ヘルスチェック (30秒間隔)
│
▼ 失敗を検出
2. RegionStatus → OFFLINE
│
▼
3. target_region 選定
(status==ONLINE かつ 最高優先度)
│
▼
4. active_region 切り替え
│
▼
5. FailoverEvent 記録
│
▼
6. アクティブリージョンのノードが新リクエストを処理
設定
config/settings.yaml:
geo_node_manager:
enabled: true
health_check_interval_seconds: 30
state_file: "data/geo/geo_state.json"
default_regions:
- id: "ap-northeast-1"
priority: 1
auto_failover: true
replication_group_size: 2 # レプリケーション先リージョン数
性能指標
| メトリクス | 目標値 | テスト参照 |
|---|---|---|
| レイテンシー行列 (10 リージョン) | < 50ms | test_latency_matrix_10_regions |
| レイテンシー行列 (50 リージョン) | < 500ms | test_latency_matrix_50_regions |
| 自動フェイルオーバー完了時間 | < 30秒 | システムテスト |
テスト
# ユニットテスト
pytest tests/unit/test_geo_node_manager.py -v
# 結合テスト
pytest tests/integration/test_features_36_39_40_integration.py::TestGeoNodeEndpoints -v
# システムテスト(マルチリージョンライフサイクル)
pytest tests/system/test_features_36_39_40_system.py::TestMultiRegionNodeLifecycle -v
# 性能テスト
pytest tests/performance/test_features_36_39_40_performance.py::TestGeoNodeManagerPerformance -v
関連ドキュメント
- SDK API Reference - Feature 40
geo_node_manager_sdk.py- 自動リカバリー
- 監査ログ