はじめに
NodIOは、ブラウザをクライアントノードとして利用し、JavaScriptベースでボランティア分散計算を実現するフレームワークです。本記事ではその背景や目的、アーキテクチャの全体像から各コンポーネントの役割までを詳細に解説します。
目次
- 背景と目的
- システム全体構成
- 各コンポーネント詳細
- オーケストレーションサーバ
- クライアント(ブラウザ)
- タスクキューとデータストア
- 通信フロー
- フェイルオーバーと冗長化
- セキュリティ考慮
- まとめ
1. 背景と目的
- 専用アプリ不要: SETI@homeやFolding@homeのようにユーザー側に別途アプリをインストールさせずに、ブラウザのみで参加可能
- 汎用性: JSONでタスク定義を行い、さまざまな並列アルゴリズムに対応
- リアルタイム性: WebSocketによる双方向通信で低レイテンシなタスク配信&結果収集を実現
2. システム全体構成
- オーケストレーションサーバ: クライアント管理、タスク配信、結果検証を統括
- Redis: タスクキューとして使用。高スループットでタスクの取得/登録を処理
- 結果ストレージ: S3やオブジェクトストレージに集約後の結果を保存
- ブラウザクライアント: WebSocket接続を維持し、JSONタスクを受信。Web Workerで並列実行
3. 各コンポーネント詳細
3.1 オーケストレーションサーバ
-
役割
- クライアントの接続管理(認証トークン発行など)
- タスクの配信/再配分
- 結果の受信と一時保管
- 冗長性チェック(重複ノードへの再配信)
-
技術スタック例
- Node.js + Express
- WebSocketライブラリ(
ws
など) - Redisクライアント(
ioredis
)
サーバサイド擬似コード
// 接続ハンドラ
wss.on('connection', socket => {
const nodeId = registerClient(socket);
socket.on('message', data => handleClientMessage(nodeId, JSON.parse(data)));
});
// タスク配信
async function dispatchTasks() {
const task = await redis.lpop('tasks');
if (task) {
const targetNode = selectAvailableNode();
targetNode.socket.send(JSON.stringify({ type: 'TASK', payload: task }));
}
}
setInterval(dispatchTasks, 50);
3.2 クライアント(ブラウザ)
-
役割
- サイト訪問時にサーバへWebSocket接続
- タスク受信 → Web Workerへ委譲
- 計算結果をサーバへ送信
-
ポイント
- メインスレッドをブロックしないようWeb Workerを活用
- 離脱時のクリーンアップ(再配分通知)
クライアント擬似コード
const socket = new WebSocket('wss://example.com');
socket.onmessage = e => {
const msg = JSON.parse(e.data);
if (msg.type === 'TASK') {
const worker = new Worker('worker.js');
worker.postMessage(msg.payload);
worker.onmessage = ev => {
socket.send(JSON.stringify({ type: 'RESULT', payload: ev.data }));
};
}
};
window.addEventListener('beforeunload', () => {
socket.send(JSON.stringify({ type: 'LEAVE' }));
});
3.3 タスクキューとデータストア
-
Redisの利用
-
LPUSH
/LPOP
で簡易タスクキュー - 冗長性のための複製リスト管理
-
-
結果ストレージ
- 中間結果をバイナリまたはJSONでS3に保管
- バッチ処理で集約・バリデーション
4. 通信フロー
- クライアント→サーバ:
HELLO
(ノード登録) - サーバ→クライアント:
TASK
(タスク配信) - クライアント→ワーカー:
RUN_TASK
- ワーカー→クライアント:
TASK_DONE
- クライアント→サーバ:
RESULT
- サーバ:
VALIDATE
→ 再配分 orACK
5. フェイルオーバーと冗長化
- 同一タスクを2〜3ノードに並行配信し、結果を照合
- タスク実行中のノード離脱検知 → 未完了タスクを再キューイング
- 定期的にノードヘルスチェック(ping/pong)
6. セキュリティ考慮
- コードサンドボックス: Web WorkerとCSPによる悪意あるコード実行の防止
- データ検証: 結果のハッシュチェック、許可トークンの検証
- 通信保護: WSS(TLS)で通信の盗聴・改竄を防止
7. まとめ
NodIOは、インストール不要かつ高い汎用性を備えたブラウザ分散計算基盤です。WebSocket+Web Worker+JSONタスク定義の組み合わせにより、低レイテンシかつ動的参加型の並列処理を実現します。本記事で紹介したアーキテクチャをベースに、次はハンズオン実装記事で具体的なコード例を見ていきましょう。