クラスター機能

注意

クラスター機能を利用する場合は事前にサポートまでご連絡ください

警告

クラスター機能は 実験的機能 のため、正式版では仕様が変更される可能性があります

概要

これは複数の Sora でクラスターを構成し、冗長化、負荷分散を行うための仕組みです。

ひとつのチャネル ID をクラスターに参加している複数の Sora で共有することができます。 そのため、Sora をクラスターに追加で参加させることで 1 チャネル単位での配信をスケールアウトさせることができます。

ここではクラスター機能ついて説明しています。

用語

ノード

クラスターに参加している Sora

リレー

ノード間での音声、映像、データの転送すること

アフィニティ

同一セッションの接続を同一ノードに集約すること

クライアントへの複数シグナリング設定

Sora SDK にシグナリング URL を複数指定することで、いずれかの ノードが正常に動作していれば Sora に繋がります。

注釈

最低 3 つの URL を渡す事を推奨しています。

リレー機能

重要

リレー機能を利用するには 最大ノード数ライセンス が必要になります。

Sora クラスターはリレーという仕組みで、クラスターに参加しているノード同士で、クライアントの音声や映像、データを共有します。

例えば 3 ノードのクラスターがある場合、すでに接続しているクライアントがいるノードとは異なるノードにクライアントが接続した場合、 Sora はその異なるノードにすでに接続しているクライアントの音声や映像、データをリレーします。

この機能を利用することで 1 チャネルでのスケールアウトを実現できるようになります。

リレー機能はクラスター機能が有効な場合に利用できます。

リレー機能はデフォルトで有効になっています。 無効にしたいしたい場合は sora.confcluster_relay を変更してください。

cluster_relay = false

リレー発生のタイミング

リレー機能利用時、リレーが発生するタイミングは別ノードに同一チャネルへ参加しているクライアントがいる場合のみです。

同一ノードのみの場合は他のノードへのリレーは発生しません。

メッセージングのリレー

リレー機能は音声と映像だけでなく、データもリレーを行います。そのため、リレー機能ではメッセージング機能も利用できます。

アフィニティ機能

重要

アフィニティ機能を利用するには 最大ノード数ライセンス が必要になります。

Sora クラスターはリレー機能利用時に、同一セッションの接続を同一ノードに集約するアフィニティ機能を提供します。

同一セッションへの接続を同一ノードに集約することでレイテンシーを低減し、より低遅延な通信を実現できます。

アフィニティ機能はデフォルトで有効になっています 無効にしたい場合は sora.confdefault_cluster_affinity を変更してください

cluster_affinity = false

アフィニティはクラスター単位でのデフォルト値以外に、セッション単位やコネクション単位で指定することもできます。

  • セッション単位の指定は、 sora.confdefault_cluster_affinity の値を上書きします

  • コネクション単位の指定は、 session.created ウェブフックの値を上書きします

特定のコネクションだけアフィニティを行わず、最初に接続したノードで WebRTC の確立を試みることもできます。

もし接続したノードがライセンスの最大同時接続数に達している場合は、 余裕のある別ノードへのリダイレクトを行います。

注釈

リレー機能を検証したい場合は sora.confdefault_cluster_affinityfalse に設定してください。

セッション単位でのアフィニティ指定

セッションウェブフック session.created の戻り値で cluster_affinity を指定することができます。

{
   "cluster_affinity": "<boolean>"
}

"cluster_affinity": true を指定した場合、そのセッションでは同一ノードへの集約を試みます。

"cluster_affinity": false を指定した場合、そのセッションでは同一ノードへの集約を行わず、接続したノードでの WebRTC 確立を試みます。

コネクション単位でのアフィニティ指定

認証ウェブフックの認証成功時の払い出しで cluster_affinity を指定することができます。

  {
.    "allowed": true,
     "cluster_affinity": "<boolean>"
  }

"cluster_affinity": true を指定した場合は、接続したノードがセッションを集約しているノードでなければ、 "type": "redirect" をクライアントへ返し、集約しているノードへの再接続を要求します。

"cluster_affinity": false を指定した場合は、ノードへの集約を行わず、接続したノードでの WebRTC 確立を試みます。

テンポラリーノード機能

重要

テンポラリーノード機能を利用するには 最大ノード数ライセンス が必要になります。

クラスター機能にはスケールアウトの目的でクラスターに一時的に登録するテンポラリーノードという仕組みがあります。

テンポラリーノードを利用すると、クラスターを気軽にスケールアウトすることができます。一時的に同時接続数を増やしたい場合に利用してください。

設定

sora.confcluster_temporary_nodetrue に設定することでテンポラリーノードとして扱われます。

cluster_temporary_node = true

登録

クラスターへの登録は RegisterClusterNode API を利用するか、 sora.confcontact_node_name_list を利用してください。

再登録

テンポラリーノードはクラスターから一度クラスターから認識されなくなると、再度クラスターに自動で再登録するには contact_node_name_list を利用する必要があります。

もし contact_node_name_list が設定されていない場合は、 RegisterClusterNode API を利用して再登録してください。

削除

テンポラリーノードはクラスターを維持するためのノードとして認識されません。そのため、クラスターへの登録も一時的なものになり、ノード破棄時に PurgeClusterNode API での削除を行う必要がありません。

注意

  • テンポラリーノードだけでクラスターを構築する事はできません

  • テンポラリーノードは InitCluster API で初期化することはできません

  • テンポラリーノードは PurgeClusterNode API でノードを削除することはできません

ノード選択とロードバランス機能

クラスターを構築しているノードの中で 現在の同時接続数ライセンスの最大同時接続数 で割った値が一番小さいノードに、新規チャネル ID のセッションを割り当てます。 この値がすべて同じ場合は、接続しに行ったノード自身が新規チャネル ID のセッションを担当します。

リレー機能無効時

すでに、そのチャネル ID がクラスター内部で利用されている場合は、 そのチャネル ID を担当しているノードへ接続先が割り当てを試みます。

ただし、そのノードの同時接続数がライセンスの上限に達していた場合、 接続に失敗します。

リレー機能アフィニティ機能有効時

すでに、そのチャネル ID がクラスター内部で利用されている場合は、 そのチャネル ID を担当しているノードへ接続先の割り当てを試みます。

担当しているノードの同時接続数がライセンスの上限に達していた場合、 他のノードへのリダイレクトを試みます。

リレー機能アフィニティ機能無効時

すでに、そのチャネル ID がクラスター内部で利用されている場合でも、 そのノードで接続を行います。

シグナリングのリダイレクト機能

重要

Sora の SDK を利用している場合は、 基本的にここに書かれているリダイレクトの細かい仕様を把握する必要はありません。

"type": "connect" を送った際、認証処理前と認証処理後に、 {"type": "redirect", "location": "wss://sora1.example.com/signaling"} が Sora から送られてくる場合があります。

この場合は、送られてきた location の URL にシグナリング URL を切り替えて再度 type: connect を行ってください。 その際は {type: connect, redirect: true} のように redirect: true を追加情報として入れてください。

HTTP API のリダイレクト機能

チャネル ID を指定する HTTP API を利用する場合、リダイレクトが発生することがあります。 指定されたチャネル ID を他ノードが担当している場合に、ステータスコード 307 (Temporary Redirect)の HTTP 応答により、クライアントにそのノードへのリダイレクトを要求します。

ステータスコード 307 の HTTP 応答受信時の処理は、HTTP のクライアントとして使用するツールやライブラリにより異なります。 必要に応じて、リダイレクト応答の Location ヘッダーへアクセスを継続するようにしてください。

たとえば、curl コマンドの場合は、 -L オプションを指定することでリダイレクト先への再要求を行います。

クラスター自動参加機能

クラスターにノードが自動で参加する機能です。

Sora はクラスターが有効な際、起動時に sora.confcontact_node_name_list に存在する ノード名に対してクラスターの参加を自動で試みます。

また、そのノードが一度でもクラスターに参加したことがある場合は、そのクラスターに参加していた時の ノード一覧を利用して、クラスターへの参加を自動で試みます。

クラスター手動参加機能

重要

sora.confcontact_node_name_list を利用したクラスター自動参加機能の利用を推奨しています。

クラスターを手動で構築する機能です。既存のクラスターに参加する際に、クラスターに参加させるノードで RegisterClusterNode API を実行します。

すでクラスターに参加しているいずれかのノードの名前を contact_node_name に指定してください。 クラスターに参加していて、初期化済みであれば、どのノードでもかまいません。

クラスター自動復旧

クラスターで利用しているネットワークに障害が発生した際には、個々のノードはクラスターを構成する他のノードへの接続を試みて、復旧処理を行います。

ネットワーク分断時の接続受け付けの停止

ネットワーク分断時には Sora のノード間で通信ができずに、クラスター内の情報の整合性が取れなくなる可能性があります。 この情報の不整合を回避するために、Sora は自分がクラスター内の半数以下のグループに属した場合には、既存の接続を切断し、 さらに新規接続の受け付けも停止します。

特定ノードへの新規チャネル ID の割り当て停止

モード機能新規コネクションブロックモード または 新規セッションブロックモード になっている場合は、 そのノードに対して新規チャネル ID の割り当てを行いません。

録画情報の共有

録画の情報はクラスター内部で共有されます。 たとえば StartRecording API をあるノードに対して実行した後にそのノードが停止しても 録画情報は他のノードに残り続けます。

合計接続数維持機能

重要

合計接続数維持機能を利用するには 最大ノード数ライセンス が必要になります。

クラスターを構築している場合、特定のノードがハードウェア障害などで利用できなくなった場合、 残りのノードで障害が発生したノードの同時接続数を引き継ぎます。

例えば 100 同時接続のノードを 3 つでクラスターを構築している場合、 1 つのノードに障害が発生した場合は 2 つのノードで 300 同時接続を維持できます。

割り当ては 1 つのノードが 150 までの同時接続数を許容できるようになります。

障害が発生したノードが復旧したとしても 100 を超えている接続を切断することはありません。 ただし 1 ノードの最大同時接続数の 100 までに戻ります。

設定

cluster

クラスター機能を利用する場合、 sora.conf にて clustertrue を設定する必要があります。

デフォルトでは cluster は有効になっていません。

重要

cluster = true にして Sora を起動した場合、 Sora は InitCluster API を実行するか、クラスターに参加して過半数のグループになったタイミングでのみ利用可能になります。

cluster = true

cluster_relay

重要

クラスターリレー機能を利用する場合は 最大ノード数ライセンス が必要になります。

クラスターリレー機能を利用する場合、 sora.conf にて clustertrue を設定する必要があります。

cluster_relay のデフォルトは true になっています。

cluster = true

default_cluster_affinity

クラスターリレー機能でアフィニティ機能を利用する場合、 sora.conf にて clustersora_conf-cluster_relay`true を設定する必要があります。

default_cluster_affinity のデフォルトは true になっています。

default_cluster_affinity = true

node_name

クラスター機能を利用する際のノード名を指定して下さい。

この名前はクラスター内のノードの識別に使われます。 具体的には、クラスターノード間の通信相手の特定や、 sora.confcontact_node_name_listRegisterClusterNode API、 PurgeClusterNode API で指定する名前として利用します。

重要

node_name はクラスター内のすべてのノードでユニークである必要があります

ノード名の @ の前には、正規表現 [0-9A-Za-z_\\-]+ にマッチする任意の文字列を指定してください。 また @ の後ろには、他のノードからアクセス可能なこのノードのドメイン名(FQDN)や、IP アドレスを指定してください。

@ の後ろにホスト名("." を含まない文字列)のみを指定すると、ノード間で通信が行えなくなってしまいますので、ご注意ください。

# ドメイン名を指定する例
node_name = node01@node01.example.com
# IP アドレスを指定する例
node_name = node02@192.0.2.1

contact_node_name_list

クラスター機能が有効な場合で、 sora.confcontact_node_name_list が指定されていた場合、 起動時に自分以外のノード名に対して自動でクラスターの参加を試みます。

注釈

自分自身のノード名が contact_node_name_list に含まれていても無視します。

node_name_list = sora1@192.0.2.1, sora2@192.0.2.2, sora3@192.0.2.3

external_signaling_url

sora.conf にてシグナリングの URL を指定して下さい。 この URL はクラスター機能を利用した際に "type": "redirect""location" の値として払い出されます。

external_signaling_url = wss://node1.example.com/signaling

例えば、上記の設定の場合は、シグナリングのリダイレクトが必要な際に Sora から {"type": "redirect", "location": "wss://node1.example.com/signaling"} として払い出されます。

external_api_url

sora.conf にて API の URL を指定して下さい。 この URL はクラスター機能を利用した際に、API を適切なノードに HTTP 307 でリダイレクトさせる場合の HTTP の location ヘッダーの値として払い出されます。

external_api_url = https://node1.example.com/api

cluster_listen_{min,max}_port

sora.conf にてクラスター情報の同期に利用する TCP の受信ポートの範囲を指定してください。

デフォルトでは 49010 - 49020 が指定されています。

cluster_listen_min_port = 49010
cluster_listen_max_port = 49020

API

クラスター利用時に挙動が変わる API

以下の API はクラスター機能が有効な場合に 全てのノードの結果 をデフォルトで返すようになります。

そのため、ノード単体での結果を取得したい場合は local パラメータに true を指定してください。

クラスター初期化 API

クラスターを構築するときは、まずクラスターの初期化を行います。

重要

クラスターの初期化はクラスターを初めて構築する際と、クラスターが破綻した際に行う必要があります。

クラスターの初期化を実行する場合は 20221221.InitCluster API をクラスター構築するいずれかのノードで実行します。 node_name_list にはクラスターを構成するノードを、 20221221.InitCluster API を実行するノードを含め指定してください。

API の詳細は InitCluster API をご確認ください。

$ http POST 127.0.0.1:3000/ x-sora-target:Sora_20221221.InitCluster \
    node_name_list:='["node-02@192.0.2.7", "node-03@192.0.2.8", "node-01@192.0.2.5"]' \
    -vvv
POST / HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 83
Content-Type: application/json
Host: 127.0.0.1:3000
User-Agent: HTTPie/3.2.2
x-sora-target: Sora_20221221.InitCluster

{
    "node_name_list": [
        "node-02@192.0.2.7",
        "node-03@192.0.2.8",
        "node-01@192.0.2.5"
    ]
}


HTTP/1.1 200 OK
access-control-allow-headers: Origin, X-Requested-With, Content-Type, Accept, x-sora-target
access-control-allow-methods: POST, OPTIONS
access-control-allow-origin: *
access-control-max-age: 1000
content-length: 80
content-type: application/json
date: Wed, 06 Dec 2023 06:52:47 GMT
server: Cowboy

{
    "node_name_list": [
        "node-02@192.0.2.7",
        "node-03@192.0.2.8",
        "node-01@192.0.2.5"
    ]
}

重要

クラスターのノードが恒久的に破損し、クラスターを構成するノードが半数以下になった場合には、 全てのノードが接続を受け付けなくなるため、クラスターの再構築手順に従って、 再度クラスターの初期化を行う必要があります。

詳しくは クラスター破綻からの再構築手順 を参照してください。

クラスター登録 API

Tip

sora.confcontact_node_name_list を利用したクラスターへの自動登録の利用を推奨しています。

参加するノードに対して、すでにクラスターに参加しているノードを指定してクラスターへ参加します。

API の詳細は RegisterClusterNode API をご確認ください。

下記は、これから参加する既存クラスター内の node-01@192.0.2.5 ノードを contact_node_name に指定して、新規に登録させるノードで RegisterClusterNode APIを実行しています。

$ http POST 127.0.0.1:3000/ x-sora-target:Sora_20211215.RegisterClusterNode \
    contact_node_name=node-01@192.0.2.5
HTTP/1.1 200 OK
content-length: 80
content-type: application/json
date: Tue, 16 Nov 2021 08:42:25 GMT
server: Cowboy

{
    "node_name_list": [
        "node-01@192.0.2.5",
        "node-02@192.0.2.7",
        "node-03@192.0.2.8"
    ]
}

クラスターノード完全消去 API

あるノードが障害で再度の参加が難しい、またはスケールインのためにノード破棄する場合は、 破棄するノードを停止後に PurgeClusterNode API を利用して、そのノード情報を完全消去してください。

20220629.PurgeClusterNode API は、クラスターに参加している破棄するノード以外のどのノードでもかまわないので 1 回だけ実行します。 この API で完全消去した結果はクラスター内部で共有されます。

警告

PurgeClusterNode API はクラスターからノードを完全に消去するための API です。 再度参加するノードに対しては基本的に使用しないでください。 この API を含めた運用の手順は cluster_operation をご確認ください。

詳細は PurgeClusterNode API をご確認ください。

$ http POST 127.0.0.1:3000/ x-sora-target:Sora_20220629.PurgeClusterNode \
    target_node_name=node-01@192.0.2.5
HTTP/1.1 200 OK
access-control-allow-headers: Origin, X-Requested-With, Content-Type, Accept, x-sora-target
access-control-allow-methods: POST, OPTIONS
access-control-allow-origin: *
access-control-max-age: 1000
content-length: 40
content-type: application/json
date: Wed, 06 Dec 2023 07:16:06 GMT
server: Cowboy

{
    "target_node_name": "node-01@192.0.2.5"
}

クラスターノード一覧 API

詳細は ListClusterNodes API をご確認ください。

$ http POST 127.0.0.1:3000/ x-sora-target:Sora_20211215.ListClusterNodes
HTTP/1.1 200 OK
content-length: 1006
content-type: application/json
date: Tue, 16 Nov 2021 08:36:25 GMT
server: Cowboy

[
    {
        "external_api_url": "http://192.0.2.5:3000/",
        "license_max_connections": 600,
        "license_max_nodes": 10,
        "license_serial_code": "ABCDEF-SRA-E001-203801-400",
        "license_type": "Experimental",
        "node_name": "node-01@192.0.2.5",
        "connected": true,
        "mode": "normal",
        "external_signaling_url": "wss://node-01.example.com/signaling",
        "version": "2023.2.0"
    },
    {
        "external_api_url": "http://192.0.2.7:3000/",
        "license_max_connections": 600,
        "license_max_nodes": 10,
        "license_serial_code": "ABCDEF-SRA-E002-203801-400",
        "license_type": "Experimental",
        "node_name": "node-02@192.0.2.7",
        "connected": true,
        "mode": "normal",
        "external_signaling_url": "wss://node-02.example.com/signaling",
        "version": "2023.2.0"
    },
    {
        "external_api_url": "http://192.0.2.8:3000/",
        "license_max_connections": 600,
        "license_max_nodes": 10,
        "license_serial_code": "ABCDEF-SRA-E003-203801-500",
        "license_type": "Experimental",
        "node_name": "node-03@192.0.2.8",
        "connected": true,
        "mode": "normal",
        "external_signaling_url": "wss://node-03.example.com/signaling",
        "version": "2023.2.0"
    }
]

クラスターチャネル割り当て一覧 API

詳細は ListClusterChannels API をご確認ください。

$ http POST 127.0.0.1:3000/ x-sora-target:Sora_20211215.ListClusterChannels
HTTP/1.1 200 OK
content-length: 461
content-type: application/json
date: Tue, 16 Nov 2021 08:42:25 GMT
server: Cowboy

[
    {
        "channel_id": "sora",
        "owners": [
           {
               "node_name": "node-01@192.0.2.5",
               "connected": true
           }
        ]
    },
    {
        "channel_id": "lemon",
        "owners": [
           {
               "node_name": "node-01@192.0.2.5",
               "connected": true
           }
        ]
    },
    {
        "channel_id": "hisui",
        "owners": [
           {
               "node_name": "node-03@192.0.2.5",
               "connected": true
           }
        ]
    },
    {
        "channel_id": "zakuro",
        "owners": [
           {
               "node_name": "node-03@192.0.2.5",
               "connected": true
           }
        ]
    }
]

シーケンス図

リレー機能かつアフィニティ機能が有効

  • アフィニティ機能により、寄せが発生する

sequenceDiagram participant C1 as クライアント1 participant C2 as クライアント2 participant S1 as Sora1 participant S2 as Sora2 participant S3 as Sora3 participant A as アプリケーションサーバー C1->>S1: "type": "connect" S1->>+A: 認証ウェブフック A-->>-S1: 200 OK<br>"allowed": true<br>"cluster_affinity": true S1->>+A: セッションウェブフック<br />"type": "session.created" A-->>-S1: 200 OK S1->>C1: "type": "offer" C1->>S1: "type": "answer" note over C1, S1: WebRTC 接続 S1->>+A: イベントウェブフック<br />"type": "connection.created" A-->>-S1: 200 OK C2->>S2: "type": "connect" S2->>+A: 認証ウェブフック A-->>-S2: 200 OK<br>"allowed": true<br>"cluster_affinity": true note left of S2: ノードアフィニティにより Sora2 へリダイレクト S2->>C2: "type": "type": "redirect" C2->>S1: "type": "connect", "redirect": true S2->>+A: 認証ウェブフック A-->>-S1: 200 OK<br />{"allowed": true} S1->>C2: "type": "offer" C2->>S1: "type": "answer" note over C2, S1: WebRTC 確立 S1->>+A: イベントウェブフック<br />"type": "connection.created" A-->>-S1: 200 OK

リレー機能が有効だが、アフィニティ機能が無効

  • アフィニティ機能による寄せが発生しない

sequenceDiagram participant C1 as クライアント1 participant C2 as クライアント2 participant S1 as Sora1 participant S2 as Sora2 participant S3 as Sora3 participant A as アプリケーションサーバー C1->>S1: "type": "connect" S1->>+A: 認証ウェブフック A-->>-S1: 200 OK<br>"allowed": true<br>"cluster_affinity": false S1->>+A: セッションウェブフック<br />"type": "session.created" A-->>-S1: 200 OK S1->>C1: "type": "offer" C1->>S1: "type": "answer" note over C1, S1: WebRTC 接続 S1->>+A: イベントウェブフック<br />"type": "connection.created" A-->>-S1: 200 OK C2->>S2: "type": "connect" S2->>+A: 認証ウェブフック A-->>-S2: 200 OK<br>"allowed": true<br>"cluster_affinity": false S2->>C2: "type": "offer" C2->>S2: "type": "answer" note over C2, S2: WebRTC 確立 S2->>+A: イベントウェブフック<br />"type": "connection.created" A-->>-S2: 200 OK

リレー機能を利用しない場合は Sora から別ノードへのリダイレクトを要求される

sequenceDiagram participant C as クライアント participant S1 as Sora1 participant S2 as Sora2 participant S3 as Sora3 participant A as アプリケーションサーバー C->>S1: "type": "connect" note over S1: このノードは同時接続が多かったので、<br>Sora2 へリダイレクト提案 S1->>C: "type": "redirect" C->>S2: "type": "connect", "redirect": true S2->>+A: 認証ウェブフック A-->>-S2: 200 OK<br />{"allowed": true} S2->>C: "type": "offer" C->>S2: "type": "answer" note over C, A: WebRTC 確立 S2->>+A: イベントウェブフック<br />"type": "connection.created" A-->>-S2: 200 OK
© Copyright 2024, Shiguredo Inc Created using Sphinx 7.2.6