DMM.comの、一番深くておもしろいトコロ。

配信サーバー「VODST」

配信サーバー「VODST」

  • このエントリーをはてなブックマークに追加

はじめに

動画配信事業部 配信基盤チームのまさきです。
この記事では、「進化する動画配信基盤」についての連載第5回目として、配信サーバー「VODST」について記載します。
日本有数のトラフィックを誇る動画配信をどのようにオンプレで処理しているのか、DMMの動画配信の歴史も交えて書きたいと思います。

目次記事はこちらです。 inside.dmm.com

その前に、ちょっとだけ... 連載3回目も書かせていただいたのですが、私自身は金沢で業務を行っています。 大規模な動画配信を金沢から作り上げていくって素敵ですね!(採用情報はページの下に!)

VODSTとは

DMMの動画配信

私たちの配信プラットフォームでは様々な動画配信を行っています。

  • VODストリーミング配信
    コンテンツのストリーミング配信
  • VODダウンロード配信
    DRMをかけたコンテンツファイルのダウンロード配信
  • ライブストリーミング配信
    ライブ映像のストリーミング配信

今回はVODストリーミング配信を処理している VODST システムについて書きたいと思います。  

DMMの配信の特徴

日本有数の動画配信プラットフォームであるDMMの動画配信には以下の特徴があります。

項目 内容
コンテンツ数が膨大 37万コンテンツ 以上
総コンテンツサイズ、10PB以上
トラフィックが多い 225Gbps(VODSTの最高トラフィック)
100Gbps(VODSTの1日平均)
(ちなみにDMM全体のオンプレ最高トラフィックは386Gbps)
コンテンツ増加数が多い 約 2000コンテンツ/月
約 120TB/月
月定額サービスがある 月定額サービスは定期的に対象コンテンツが入れ替わる。
入れ替わりのタイミングで対象コンテンツの視聴数が増加する
定期的なキャンペーンがある 古い作品もキャンペーン対象になると視聴数が増加する
オンプレ配信 物理サーバー100台以上(VODSTで使用しているサーバー)

記載した値はざっくりとしたものですが、規模感は分かっていただけるかと思います。 クラウド化することで運用は楽になると思いますが、配信規模が大きいこともあり、オンプレサーバーのチューニングを行ってパフォーマンスを最大限に引き出すことで、クラウドよりも遥かに高いコストパフォーマンスを実現しています。連載11回目に予定している「配信基盤を支えるオンプレ技術」の話で、このあたりの内容に触れられるかもしれません。

VODSTの歴史

スマホの登場、高速ネット環境の実現、デバイスの増加や高画質化 等々、直近10年で動画配信を取り巻く環境は大きく変化しました。そして、その環境変化に合わせ、VODSTも課題解決を繰り返して進化してきました。簡単にその変遷をまとめました。

世代 配信形式 ソフトウェア 主な特徴
~2012 v1 ・HLS
・RTSP
・Smooth Streamig
・Wowza Media Server
・Windows Media Services
スマホ向けストリーミング配信開始
運用開始時はアクティブ/スタンバイ構成4台
最大トラフィック2Gbps
2012~2016 v2 ・HLS
・Smooth Streamig
・Wowza Media Server
・nginx
・GlusterFS
トラフィック、コンテンツの急速な増加に対応
・DNSによる負荷分散構成に変更
・キャッシュサーバー導入
2016~2019 v3 ・HLS
・Smooth Streamig
・Wowza Streaming Engine
・nginx
・Scality
・GlusterFS
サーバー、コンテンツ増加に伴う運用コストの削減
・処理の共通化/最適化を行い汎用的な配信システムを開発
・サーバー構築をコード化
・Scality導入によるストレージ大容量化
2019~ v4 ・HLS
・Smooth Streamig
・MPEG-DASH
・Wowza Streaming Engine
・OpenResty
・Consul
・Scality
・GlusterFS
配信システムのインテリジェンス化
・キャッシュ制御
・動的負荷分散
・ノード管理

VODSTv3の課題

v4の説明の前に、V3の課題について少し説明したいと思います。

ストリーミングサーバーはload averageが上昇しやすく、なるべく前段のキャッシュサーバーで捌くのが理想です。v3ではキャッシュノードをDNSラウンドロビンで負荷分散をしていました。

f:id:yanoshi:20200227152541p:plain
VODSTv3の負荷分散アーキテクチャ
しかし、この構成ではキャッシュサーバーを増やしても、一定台数を超えてくるとサーバー増加分の効果が出ないようになります。
理由として以下が考えられます。

1. キャッシュサーバーを追加
2. キャッシュの無いサーバーが増加
3. キャッシュヒット率が低下
4. ストリーミングサーバーの負荷が下がらない(下手をすると負荷が上がる)

ではそれならば、ストリーミングサーバーを増やせば良いのではとなるのですが、今度はストレージサーバーから取得するサーバーが増えることで発生するオーバヘッドが大きくなり、ストレージサーバーの負荷が上がります。

結局、スケールアウトの効果が望める規模での配信システムのセット(キャッシュ、ストリーミング、ストレージ)を複数セット構築し、コンテンツを分散させることで、負荷分散を行いました。これにより確かに負荷分散はできたのですが、以下の課題が出てきました。

  • サーバーリソースの無駄が多い
    配信セット単位で冗長化や突発的なトラフィック増加に備えて余力を作る必要があるため、配信セットが増えるほど無駄も増える。
  • 配信セットが増加していく
    コンテンツ分散しているため、コンテンツの増加に合わせて配信セットを増やす必要がある。配信セットが増えることで、さらにサーバーリソースの無駄が増える
  • 負荷対策の運用コストが高い
    キャンペーンや月定額サービスでコンテンツの入れ替わり時に対象作品の視聴数が増加。配信セットで負荷に耐えられなくなることを防ぐために、予め対象作品をCDNから配信する設定を行ったり、通常の配信セットとは別に月定額用の配信セットを用意したりして、毎月コンテンツの入れ替えを行う。

長々と書きましたが、まとめると
v3は上手くキャッシュ制御ができないため、運用も含めコストパフォーマンスが非常に悪いシステムでした。

そして、これらの課題を解決するためにv4の開発に取り組みました。

VODSTv4アーキテクチャ

v4では、v3の課題の根本原因であったキャッシュ制御をアーキテクチャーの中心として開発を行いました。

VODSTv4ソフトウェア構成

f:id:yanoshi:20200227152713p:plain

  • Redirector
    コンテンツ、負荷分散情報から配信先の振り分けを行う
  • Cache
    ストリーミングデータをキャッシュするSSD搭載の高速サーバー
  • Streamer
    Wowza Streaming Engineを使用してストリーミング配信を行う。Wowzaの前段にはOpenRestyを配置
  • VODST Manager
    各配信ノードからリクエスト情報を収集し、コンテンツ単位の負荷分散情報を生成。他に各ノードの情報やシステム設定なども管理

ソフトウェア

VODSTv4を支えている主なソフトウェアを紹介します。

Wowza Streaming Engine

Wowza Media SystemsのJavaで動作する動画ストリーミングサーバーです。VODSTではHLS、Smooth Streaming、MPEG-DASH のストリーミング配信を行っています。 WowzaはGUIで簡単に配信設定を行うことができる一方、Javaでカスタムモジュールを作ることで複雑なことにも柔軟に対応できます。 VODSTでも以下の処理をカスタムモジュールで対応しています。

  • ABR(Adaptive bitrate)配信の動的設定
    SMILという形式のファイルに設定を定義することでABR配信を行うことができますが、ビットレートの組み合わせごとにファイルを事前に準備しておく必要があります。DMMの動画配信はSD/HD配信、コンテンツを作成した時期、VR配信などコンテンツより複数の組み合わせが存在しSMILファイルの管理が煩雑になります。 そこで、URLにABR情報を埋め込み、カスタムモジュールでURLから動的にABR設定を行うことで、SMILファイルの管理をなくし、柔軟なABR設定を行っています。

  • DRMの動的設定
    標準ではkeyファイルに各DRM(Widevine、PlayReady、FairPlay Streaming)の設定(keyidやcontent-key等)を定義し、コンテンツファイルごとにkeyファイルを準備しておく必要があります。DMMのコンテンツファイルは膨大であり、keyファイルも膨大になります。また販売方法やサービスによって、同じコンテンツでも複数の異なるkey設定を行っているため、ファイルベースの管理はセキュリティ面からも大変になります。
    そこで、カスタムモジュールで配信時のパラメータに応じて動的にkey情報を設定し、柔軟なDRMを行っています。

  • 不正アクセス防止
    不正なアクセスをブロックするために、ストリームセッションが作成されるイベントでURLなどをチェックし、不正な場合はリジェクトする処理を行っています。

www.wowza.com

OpenReasty

nginx、LuaJIT、Luaライブラリ、サードパーティのnginxモジュールを統合したWebプラットフォームです。conf設定だけでは難しい処理もLuaスクリプトで簡単に実装でき、その柔軟性やnginxの高速性、インストールの簡単さなどでとても優れたWebプラットフォームだと思います。 VODSTでは多くのノードでOpenRestyが動いており、配信ノードの選択、リクエスト情報の収集、認証、キャッシュクリア処理など様々な処理をLuaで実装しています。

配信基盤ではVODST以外にも多くのシステムにOpenRestyを使用しています。
openresty.org

Consul

システムの各ノードに入れておくことで、各ノード間の情報共有や通知などノードを繋げるための便利な機能を提供してくれるのがHashiCorp社のConsulです。
VODSTで使用しているConsulの機能を紹介します。

  • サービスのノード取得
    例えば、キャッシュノードをキャッシュサービスとして登録すれば、DNSやHTTP APIで簡単にキャッシュノードを取得できます。
    サービスのヘルスチェックもでき、正常なノードリストを簡単に取得できます。取得したリストから使用するノードを決定するようにしておけば、サービスに異常があるノードを自動的にサービスから外すことができるようになります。
  • イベント通知
    Consul Watchに任意のイベントを登録しておき、ConsulコマンドやAPIでイベントを発火させることで、クラスタ内のConsulノードでイベントを受け取り、登録しておいた処理を実行させることができます。

この他にもKV storeなどいろいろな機能がありますので、ぜひ確認してみてください!
www.consul.io

キャッシュ制御

Redirectorでは、コンテンツ単位の負荷分散情報を元に配信先のノードを決定します。 負荷分散情報は、使用するキャッシュノード数やCDNを使用するかどうかなどの情報を持っており、これを元に配信先を決定しています。
配信先がキャッシュサーバーの場合、コンテンツIDをキーにノードマッピングし、コンテンツ単位で振り分けるキャッシュノードを固定にすることで、キャッシュヒット率を向上させました。
この際に問題となるのが、ノードの増減によりキャッシュノードのマッピングが変わり、再キャッシュが発生してしまう点です。例えば、単純にコンテンツIDからハッシュ値を求めてノード数による剰余でマッピングした場合、ノード数が変わるとキャッシュノードが変わり、全て再キャッシュとなって大変な事態になってしまいます。この問題の解決方法として、Consistent hashingによるノードをマッピングする方法があります。アルゴリズムについては割愛しますが、この方法によりノード増減による再キャッシュを最小限にできます。

VODSTでは、Consistent hashingより単純な計算で、かつ高速な Jump consistent hash でノードマッピングしています。 Jump consistent hash は高速ですが、欠点もあります。ノードがシーケンシャルに増加するぶんには問題ありませんが、ノードが減った場合にノードの位置によって全体的に影響が出てしまう点です。
(参考:Jump consistent hashの論文「A Fast, Minimal Memory, Consistent Hash Algorithm」)

具体的に1~10000をキーとした10000個をJump consistent hashで振り分けた場合のノード変更時のキャッシュ率について、表にまとめました。
※キャッシュ率:ノード変更前の状態で100%キャッシュされていたとし、ノード変更後に振り分けた場合に既にキャッシュがある割合とします。

ノード番号 10ノードから
11ノードに増加
11ノードから
12ノードに増加
10ノードから
ノード3を削除
ノード1 100% 100% 90.5%
ノード2 100% 100% 90.1%
ノード3 100% 100% -
ノード4 100% 100% 0%
ノード5 100% 100% 0%
ノード6 100% 100% 0%
ノード7 100% 100% 0%
ノード8 100% 100% 0%
ノード9 100% 100% 0%
ノード10 100% 100% 9.7%
ノード11 0% 100% -
ノード12 - 0% -

上記のように、ノードが増えるぶんには既存のノードには全く影響が出ません。しかしノードが減った場合、なくなったノード以降のノードは、ほぼ再キャッシュが必要となります。

そこでVODSTでは、この欠点をカバーしたJump consistent hashのLuaライブラリを使用しています。このライブラリでは、なくなったノードにマッピングされたものを別ノードに振り分けることで、ノードが減った際の全体への影響を小さくしています。 ただし、ノードが既に歯抜けの状態でノードの増減があった場合には影響の大きいノードが発生しますので、歯抜けの状態が続くようならば、後ろのノードを歯抜けのところに移動してシーケンシャルな状態になるように変更したほうが良いかもしれません。

ライブラリを使用したキャッシュ率は以下になります。

ノード番号 10ノードから
ノード3を削除
左の状態から
ノード6を削除
左の状態から
ノード9を削除
ノード1 90.5% 89.2% 87.9%
ノード2 90.1% 87.4% 87.8%
ノード3 - - -
ノード4 90.9% 88.2% 87.8%
ノード5 88.8% 89.3% 87.7%
ノード6 88.5% - -
ノード7 89.6% 88.2% 87.8%
ノード8 89.7% 87.4% 12.0%
ノード9 90.2% 11.3% -
ノード10 92.4% 0% 88.7%

2つ目のノード削除以降で、大きく影響が出ているノードが発生しています。

動的負荷分散

VODST Managerが配信ノードからアクセス情報の収集・コンテンツ単位に集計を行い、集計結果から負荷分散情報を作成し、その情報を元に配信ノードが負荷分散を行っています。
その処理フローを簡単に説明したいと思います。

  1. 配信ノードにリクエストが来た際に、アクセス情報をOpenRestyのshared dictに保持
  2. VODST Managerが定期的に、配信ノードに保持されてるアクセス情報を収集
  3. 収集したアクセス情報をコンテンツ単位に集計
  4. 集計結果からコンテンツ単位の負荷分散情報を更新する
  5. 負荷分散情報の更新が完了したら、Consulを利用して負荷分散情報の更新イベントを発火させる
  6. 配信ノードは負荷分散情報の更新イベントを受け、VODST Managerから負荷分散情報を取得する。
  7. 配信ノードは取得した負荷分散情報をOpenRestyのshared dictに保持する
  8. 配信ノードはストリーミングのリクエストが来たら、shared dictにある負荷分散情報から配信先を決定する

VODSTは数秒間隔で上記の処理を実行しており、ほぼリアルタイムに負荷分散情報を更新しています。

視聴状況 負荷分散
直近の視聴なし ストリーミングサーバーから配信
同時視聴が少ない キャッシュノード数を少なく割り当てる
同時視聴が多い キャッシュノード数を多く割り当てる
同時視聴数がとても多い CDNを使用

また、ピークタイムと通常時で時間帯に応じて負荷分散を調整することで、より効率的な配信を行っています。 例えば、サーバーに余裕のある時間帯ではCDNへの振り分けを抑えることで、CDNコストを下げています。

高可用性

キャッシュ制御、動的負荷分散といろいろな処理をしていますが、最も優先すべき機能はストリーミング配信を停止させないということです。
VODSTでは配信に必要な情報はノード自身が保持し、配信ノード単体で動作するように設計しています。そのためVODST Managerがダウンしてもストリーミング配信が停止することはありません。 また、Consulによるノード、サービス管理を行い、自動的に障害点をサービスアウトさせてサービスに影響が出ないようにしています。

また、キャッシュ制御によりスケールアウトで効果的な負荷分散ができるようになり、v3のように配信セットを分ける必要がなく、数十台のキャッシュノード構成にできるようになりました。そのため、数ノードに問題が発生しても残りのノードで問題なくカバーできるようになりました。

ログ

アクセス情報を収集する仕組みにより、ストリーム単位でリクエストログを簡単に取得できるようになり、問題発生時の原因調査の役に立っています。

ダウンロード配信

実はDMM PLayer v2で使用しているdcvファイルは、VODSTv4から配信しています。 連載2回目に「オンザフライでファイル結合」の記事があります。この結合アプリケーションはVODSTv4上で動作しており、ストリーミングをdcvファイルにオンザフライで生成しています。

VODSTv4の効果

v4は1年以上稼働しており、その効果について記載します。

項目 内容
キャッシュヒット率 40%(v3)→80%に向上
物理サーバー台数削減 20%削減。キャッシュヒット率が向上することで、効率的なリソース活用ができるようになった。
CDN費用削減 70%削減。動的負荷分散により、必要な時だけCDNを使用するようになった
配信安定化 突発的に視聴数が多い配信があっても、自動的にCDNに負荷分散することで安定した配信が実現
負荷対策の運用 不要になった

v3の課題を解決し、コストパフォーマンスが改善され、非常に良い効果を得ることができました!

あとがき

急速に変化していく環境で常にいろいろな課題を抱えてきましたが、インフラチームと協力しながら常に進化させてきました。
v4の開発でも、ITインフラ本部 インフラ部 動画配信チームの協力のもと実現でき、感謝しております。 v4になり負荷対策で苦しむこともなくなって、運用でも多くの作業が不要になりコストも削減できました。しかし、環境は常に変化し続けています。だからこそ、システムも常に進化させて環境に素早く対応し、より快適な動画配信を目指したいと思いますので、今後ともよろしくお願い致します。

採用情報

DMM Groupでは金沢採用も含めて新卒/中途問わず、一緒に働く仲間を募集しています! 少しでも興味を持っていただいたあなたのエントリーをお待ちしております。

新卒採用(金沢勤務)

新卒採用(採用ポータル)

dmm-corp.com